From d3fdb7d8d6d11fc83dde384b524066954880e28f Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Mon, 26 Aug 2024 14:58:31 -0400 Subject: [PATCH 01/38] [ResponseOps][TaskManager] fix limited concurrency starvation in mget task claimer (#187809) resolves #184937 ## Summary Fixes problem with limited concurrency tasks potentially starving unlimited concurrency tasks, by using `_msearch` to search limited concurrency tasks separately from unlimited concurrency tasks. ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed --------- Co-authored-by: Elastic Machine Co-authored-by: Mike Cote --- .../mark_available_tasks_as_claimed.test.ts | 128 +++++++++++++ .../mark_available_tasks_as_claimed.ts | 60 ++++-- .../server/task_claimers/index.ts | 9 + .../lib/task_selector_by_capacity.ts | 40 ++++ .../task_claimers/strategy_mget.test.ts | 175 ++++++++++++------ .../server/task_claimers/strategy_mget.ts | 166 +++++++++++------ .../task_manager/server/task_store.mock.ts | 2 + .../task_manager/server/task_store.test.ts | 135 ++++++++++++++ .../plugins/task_manager/server/task_store.ts | 97 ++++++++-- 9 files changed, 662 insertions(+), 150 deletions(-) create mode 100644 x-pack/plugins/task_manager/server/task_claimers/lib/task_selector_by_capacity.ts diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts index 103bc17004ef0..76df8b7ae5584 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts @@ -18,8 +18,11 @@ import { RecognizedTask, OneOfTaskTypes, tasksWithPartitions, + claimSort, } from './mark_available_tasks_as_claimed'; +import { TaskStatus, TaskPriority, ConcreteTaskInstance } from '../task'; + import { TaskTypeDictionary } from '../task_type_dictionary'; import { mockLogger } from '../test_utils'; @@ -304,4 +307,129 @@ if (doc['task.runAt'].size()!=0) { } `); }); + + // Tests sorting 3 tasks with different priorities, runAt/retryAt values + // running the sort over all permutations of them. + describe('claimSort', () => { + const definitions = new TaskTypeDictionary(mockLogger()); + definitions.registerTaskDefinitions({ + normalPriorityTask: { + title: 'normal priority', + createTaskRunner: () => ({ run: () => Promise.resolve() }), + priority: TaskPriority.Normal, // 50 + }, + noPriorityTask: { + title: 'no priority', + createTaskRunner: () => ({ run: () => Promise.resolve() }), + priority: undefined, // 50 + }, + lowPriorityTask: { + title: 'low priority', + createTaskRunner: () => ({ run: () => Promise.resolve() }), + priority: TaskPriority.Low, // 1 + }, + }); + + // possible ordering of tasks before sort + const permutations = [ + [0, 1, 2], + [0, 2, 1], + [1, 0, 2], + [1, 2, 0], + [2, 0, 1], + [2, 1, 0], + ]; + + test('works correctly with same dates, different priorities', () => { + const date = new Date(); + const baseTasks: ConcreteTaskInstance[] = []; + + // push in reverse order + baseTasks.push(buildTaskInstance({ taskType: 'lowPriorityTask', runAt: date })); + baseTasks.push(buildTaskInstance({ taskType: 'noPriorityTask', runAt: date })); + baseTasks.push(buildTaskInstance({ taskType: 'normalPriorityTask', runAt: date })); + + for (const perm of permutations) { + const tasks = [baseTasks[perm[0]], baseTasks[perm[1]], baseTasks[perm[2]]]; + const sorted = claimSort(definitions, tasks); + // all we know is low should be last + expect(sorted[2]).toBe(baseTasks[0]); + } + }); + + test('works correctly with same priorities, different dates', () => { + const baseDate = new Date('2024-07-29T00:00:00Z').valueOf(); + const baseTasks: ConcreteTaskInstance[] = []; + + // push in reverse order + baseTasks.push( + buildTaskInstance({ taskType: 'noPriorityTask', runAt: new Date(baseDate + 1000) }) + ); + baseTasks.push(buildTaskInstance({ taskType: 'noPriorityTask', runAt: new Date(baseDate) })); + baseTasks.push( + buildTaskInstance({ taskType: 'noPriorityTask', runAt: new Date(baseDate - 1000) }) + ); + + for (const perm of permutations) { + const tasks = [baseTasks[perm[0]], baseTasks[perm[1]], baseTasks[perm[2]]]; + const sorted = claimSort(definitions, tasks); + expect(sorted[0]).toBe(baseTasks[2]); + expect(sorted[1]).toBe(baseTasks[1]); + expect(sorted[2]).toBe(baseTasks[0]); + } + }); + + test('works correctly with mixed of runAt and retryAt values', () => { + const baseDate = new Date('2024-07-29T00:00:00Z').valueOf(); + const baseTasks: ConcreteTaskInstance[] = []; + + // push in reverse order + baseTasks.push( + buildTaskInstance({ taskType: 'noPriorityTask', runAt: new Date(baseDate + 1000) }) + ); + baseTasks.push( + buildTaskInstance({ + taskType: 'noPriorityTask', + runAt: new Date(baseDate - 2000), + retryAt: new Date(baseDate), // should use this value + }) + ); + baseTasks.push( + buildTaskInstance({ taskType: 'noPriorityTask', runAt: new Date(baseDate - 1000) }) + ); + + for (const perm of permutations) { + const tasks = [baseTasks[perm[0]], baseTasks[perm[1]], baseTasks[perm[2]]]; + const sorted = claimSort(definitions, tasks); + expect(sorted[0]).toBe(baseTasks[2]); + expect(sorted[1]).toBe(baseTasks[1]); + expect(sorted[2]).toBe(baseTasks[0]); + } + }); + }); }); + +interface BuildTaskOpts { + taskType: string; + runAt: Date; + retryAt?: Date; +} + +let id = 1; + +function buildTaskInstance(opts: BuildTaskOpts): ConcreteTaskInstance { + const { taskType, runAt, retryAt } = opts; + return { + taskType, + id: `${id++}`, + runAt, + retryAt: retryAt || null, + scheduledAt: runAt, + attempts: 0, + status: TaskStatus.Idle, + startedAt: null, + state: {}, + params: {}, + ownerId: null, + }; +} diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts index 107a3f4466637..4e138545aec25 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -6,7 +6,7 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TaskTypeDictionary } from '../task_type_dictionary'; -import { TaskStatus, TaskPriority } from '../task'; +import { TaskStatus, TaskPriority, ConcreteTaskInstance } from '../task'; import { ScriptBasedSortClause, ScriptClause, @@ -15,23 +15,6 @@ import { MustNotCondition, } from './query_clauses'; -export function taskWithLessThanMaxAttempts(type: string, maxAttempts: number): MustCondition { - return { - bool: { - must: [ - { term: { 'task.taskType': type } }, - { - range: { - 'task.attempts': { - lt: maxAttempts, - }, - }, - }, - ], - }, - }; -} - export function tasksOfType(taskTypes: string[]): estypes.QueryDslQueryContainer { return { bool: { @@ -166,12 +149,53 @@ function getSortByPriority(definitions: TaskTypeDictionary): estypes.SortCombina }; } +// getClaimSort() is used to generate sort bits for the ES query +// should align with claimSort() below export function getClaimSort(definitions: TaskTypeDictionary): estypes.SortCombinations[] { const sortByPriority = getSortByPriority(definitions); if (!sortByPriority) return [SortByRunAtAndRetryAt]; return [sortByPriority, SortByRunAtAndRetryAt]; } +// claimSort() is used to sort tasks returned from a claimer by priority and date. +// Kept here so it should align with getClaimSort() above. +// Returns a copy of the tasks passed in. +export function claimSort( + definitions: TaskTypeDictionary, + tasks: ConcreteTaskInstance[] +): ConcreteTaskInstance[] { + const priorityMap: Record = {}; + tasks.forEach((task) => { + const taskType = task.taskType; + const priority = getPriority(definitions, taskType); + priorityMap[taskType] = priority; + }); + + return tasks.slice().sort(compare); + + function compare(a: ConcreteTaskInstance, b: ConcreteTaskInstance) { + // sort by priority, descending + const priorityA = priorityMap[a.taskType] ?? TaskPriority.Normal; + const priorityB = priorityMap[b.taskType] ?? TaskPriority.Normal; + + if (priorityA > priorityB) return -1; + if (priorityA < priorityB) return 1; + + // then sort by retry/runAt, ascending + const runA = a.retryAt?.valueOf() ?? a.runAt.valueOf() ?? 0; + const runB = b.retryAt?.valueOf() ?? b.runAt.valueOf() ?? 0; + + if (runA < runB) return -1; + if (runA > runB) return 1; + + return 0; + } +} + +function getPriority(definitions: TaskTypeDictionary, taskType: string): TaskPriority { + return definitions.get(taskType)?.priority ?? TaskPriority.Normal; +} + export interface UpdateFieldsAndMarkAsFailedOpts { fieldUpdates: { [field: string]: string | number | Date; diff --git a/x-pack/plugins/task_manager/server/task_claimers/index.ts b/x-pack/plugins/task_manager/server/task_claimers/index.ts index ff4f9f6131120..fdbe9e94aa6a9 100644 --- a/x-pack/plugins/task_manager/server/task_claimers/index.ts +++ b/x-pack/plugins/task_manager/server/task_claimers/index.ts @@ -83,3 +83,12 @@ export function isTaskTypeExcluded(excludedTaskTypePatterns: string[], taskType: return false; } + +export function getExcludedTaskTypes( + definitions: TaskTypeDictionary, + excludedTaskTypePatterns: string[] +) { + return definitions + .getAllTypes() + .filter((taskType) => isTaskTypeExcluded(excludedTaskTypePatterns, taskType)); +} diff --git a/x-pack/plugins/task_manager/server/task_claimers/lib/task_selector_by_capacity.ts b/x-pack/plugins/task_manager/server/task_claimers/lib/task_selector_by_capacity.ts new file mode 100644 index 0000000000000..531357436c0bf --- /dev/null +++ b/x-pack/plugins/task_manager/server/task_claimers/lib/task_selector_by_capacity.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 { ConcreteTaskInstance } from '../../task'; +import { isLimited, TaskClaimingBatches } from '../../queries/task_claiming'; + +// given a list of tasks and capacity info, select the tasks that meet capacity +export function selectTasksByCapacity( + tasks: ConcreteTaskInstance[], + batches: TaskClaimingBatches +): ConcreteTaskInstance[] { + // create a map of task type - concurrency + const limitedBatches = batches.filter(isLimited); + const limitedMap = new Map(); + for (const limitedBatch of limitedBatches) { + const { tasksTypes, concurrency } = limitedBatch; + limitedMap.set(tasksTypes, concurrency); + } + + // apply the limited concurrency + const result: ConcreteTaskInstance[] = []; + for (const task of tasks) { + const concurrency = limitedMap.get(task.taskType); + if (concurrency == null) { + result.push(task); + continue; + } + + if (concurrency > 0) { + result.push(task); + limitedMap.set(task.taskType, concurrency - 1); + } + } + + return result; +} diff --git a/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.test.ts b/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.test.ts index 959fa3468b238..4e47581ccbdd5 100644 --- a/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.test.ts +++ b/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.test.ts @@ -8,6 +8,8 @@ import _ from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { filter, take, toArray } from 'rxjs'; +import { SavedObjectsErrorHelpers } from '@kbn/core/server'; + import { CLAIM_STRATEGY_MGET, DEFAULT_KIBANAS_PER_PARTITION } from '../config'; import { @@ -34,7 +36,6 @@ import apm from 'elastic-apm-node'; import { TASK_MANAGER_TRANSACTION_TYPE } from '../task_running'; import { ClaimOwnershipResult } from '.'; import { FillPoolResult } from '../lib/fill_pool'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { TaskPartitioner } from '../lib/task_partitioner'; import type { MustNotCondition } from '../queries/query_clauses'; import { @@ -166,12 +167,12 @@ describe('TaskClaiming', () => { } for (let i = 0; i < hits.length; i++) { - store.fetch.mockResolvedValueOnce({ docs: hits[i], versionMap: versionMaps[i] }); - store.getDocVersions.mockResolvedValueOnce(docVersion[i]); - const oneBulkGetResult = hits[i].map((hit) => asOk(hit)); - store.bulkGet.mockResolvedValueOnce(oneBulkGetResult); + store.msearch.mockResolvedValueOnce({ docs: hits[i], versionMap: versionMaps[i] }); + store.getDocVersions.mockResolvedValueOnce(versionMaps[i]); const oneBulkResult = hits[i].map((hit) => asOk(hit)); store.bulkUpdate.mockResolvedValueOnce(oneBulkResult); + const oneBulkGetResult = hits[i].map((hit) => asOk(hit)); + store.bulkGet.mockResolvedValueOnce(oneBulkGetResult); } const taskClaiming = new TaskClaiming({ @@ -235,12 +236,12 @@ describe('TaskClaiming', () => { ); expect(mockApmTrans.end).toHaveBeenCalledWith('success'); - expect(store.fetch.mock.calls).toMatchObject({}); + expect(store.msearch.mock.calls).toMatchObject({}); expect(store.getDocVersions.mock.calls).toMatchObject({}); return results.map((result, index) => ({ result, args: { - search: store.fetch.mock.calls[index][0] as SearchOpts & { + search: store.msearch.mock.calls[index][0] as SearchOpts[] & { query: MustNotCondition; }, }, @@ -273,8 +274,8 @@ describe('TaskClaiming', () => { }, }); - store.fetch.mockReset(); - store.fetch.mockRejectedValue(new Error('Oh no')); + store.msearch.mockReset(); + store.msearch.mockRejectedValue(new Error('Oh no')); await expect( getAllAsPromise( @@ -337,7 +338,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce( @@ -380,7 +381,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -435,7 +439,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[2]].map(asOk)); @@ -475,7 +479,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(2); expect(store.bulkUpdate).toHaveBeenNthCalledWith( @@ -526,7 +533,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[2]].map(asOk)); @@ -578,7 +585,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(2); expect(store.bulkUpdate).toHaveBeenNthCalledWith( @@ -629,7 +639,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[2]].map(asOk)); @@ -673,7 +683,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkGet).toHaveBeenCalledWith(['id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(2); @@ -720,7 +733,7 @@ describe('TaskClaiming', () => { const fetchedTasks: ConcreteTaskInstance[] = []; const { versionMap } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); const taskClaiming = new TaskClaiming({ logger: taskManagerLogger, @@ -752,7 +765,10 @@ describe('TaskClaiming', () => { expect(taskManagerLogger.debug).not.toHaveBeenCalled(); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).not.toHaveBeenCalled(); expect(store.bulkGet).not.toHaveBeenCalled(); expect(store.bulkUpdate).not.toHaveBeenCalled(); @@ -777,7 +793,7 @@ describe('TaskClaiming', () => { const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); versionMap.delete('id-1'); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[1], fetchedTasks[2]].map(asOk)); @@ -816,7 +832,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(1); expect(store.bulkUpdate).toHaveBeenCalledWith( @@ -859,7 +878,7 @@ describe('TaskClaiming', () => { const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); docLatestVersions.delete('task:id-1'); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[1], fetchedTasks[2]].map(asOk)); @@ -898,7 +917,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(1); expect(store.bulkUpdate).toHaveBeenCalledWith( @@ -941,7 +963,7 @@ describe('TaskClaiming', () => { const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); docLatestVersions.set('task:id-1', { esId: 'task:id-1', seqNo: 33, primaryTerm: 33 }); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce([fetchedTasks[1], fetchedTasks[2]].map(asOk)); @@ -980,7 +1002,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith(['task:id-1', 'task:id-2', 'task:id-3']); expect(store.bulkUpdate).toHaveBeenCalledTimes(1); expect(store.bulkUpdate).toHaveBeenCalledWith( @@ -1025,7 +1050,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkGet.mockResolvedValueOnce( @@ -1068,7 +1093,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -1130,7 +1158,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkUpdate.mockResolvedValueOnce( [fetchedTasks[0], fetchedTasks[1], fetchedTasks[2], fetchedTasks[3]].map(asOk) @@ -1184,7 +1212,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -1244,7 +1275,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkUpdate.mockResolvedValueOnce( [fetchedTasks[0], fetchedTasks[1], fetchedTasks[2], fetchedTasks[3]].map(asOk) @@ -1288,7 +1319,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -1348,7 +1382,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkUpdate.mockResolvedValueOnce([ asOk(fetchedTasks[0]), @@ -1404,7 +1438,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -1464,7 +1501,7 @@ describe('TaskClaiming', () => { ]; const { versionMap, docLatestVersions } = getVersionMapsFromTasks(fetchedTasks); - store.fetch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); + store.msearch.mockResolvedValueOnce({ docs: fetchedTasks, versionMap }); store.getDocVersions.mockResolvedValueOnce(docLatestVersions); store.bulkUpdate.mockRejectedValueOnce(new Error('oh no')); store.bulkGet.mockResolvedValueOnce([]); @@ -1506,7 +1543,10 @@ describe('TaskClaiming', () => { { tags: ['claimAvailableTasksMget'] } ); - expect(store.fetch.mock.calls[0][0]).toMatchObject({ size: 40, seq_no_primary_term: true }); + expect(store.msearch.mock.calls[0][0]?.[0]).toMatchObject({ + size: 40, + seq_no_primary_term: true, + }); expect(store.getDocVersions).toHaveBeenCalledWith([ 'task:id-1', 'task:id-2', @@ -1567,13 +1607,7 @@ describe('TaskClaiming', () => { createTaskRunner: jest.fn(), }, }); - const [ - { - args: { - search: { query }, - }, - }, - ] = await testClaimAvailableTasks({ + const claimedResults = await testClaimAvailableTasks({ storeOpts: { taskManagerId, definitions, @@ -1583,6 +1617,13 @@ describe('TaskClaiming', () => { claimOwnershipUntil: new Date(), }, }); + const [ + { + args: { + search: [{ query }], + }, + }, + ] = claimedResults; expect(query).toMatchInlineSnapshot(` Object { @@ -1786,24 +1827,31 @@ describe('TaskClaiming', () => { const taskStore = taskStoreMock.create({ taskManagerId }); taskStore.convertToSavedObjectIds.mockImplementation((ids) => ids.map((id) => `task:${id}`)); for (const docs of taskCycles) { - taskStore.fetch.mockResolvedValueOnce({ docs, versionMap: new Map() }); - taskStore.updateByQuery.mockResolvedValueOnce({ - updated: docs.length, - version_conflicts: 0, - total: docs.length, + const versionMap = new Map(); + const docVersions = new Map(); + for (const doc of docs) { + const esId = `task:${doc.id}`; + versionMap.set(doc.id, { esId, seqNo: 42, primaryTerm: 666 }); + docVersions.set(esId, { esId, seqNo: 42, primaryTerm: 666 }); + } + taskStore.msearch.mockResolvedValueOnce({ docs, versionMap }); + taskStore.getDocVersions.mockResolvedValueOnce(docVersions); + const updatedDocs = docs.map((doc) => { + doc = { ...doc, retryAt: null }; + return asOk(doc); }); + taskStore.bulkUpdate.mockResolvedValueOnce(updatedDocs); + taskStore.bulkGet.mockResolvedValueOnce(updatedDocs); } - taskStore.fetch.mockResolvedValue({ docs: [], versionMap: new Map() }); - taskStore.updateByQuery.mockResolvedValue({ - updated: 0, - version_conflicts: 0, - total: 0, - }); + taskStore.msearch.mockResolvedValue({ docs: [], versionMap: new Map() }); + taskStore.getDocVersions.mockResolvedValue(new Map()); + taskStore.bulkUpdate.mockResolvedValue([]); + taskStore.bulkGet.mockResolvedValue([]); const taskClaiming = new TaskClaiming({ logger: taskManagerLogger, - strategy: 'default', + strategy: CLAIM_STRATEGY_MGET, definitions, excludedTaskTypes: [], unusedTypes: [], @@ -1817,7 +1865,21 @@ describe('TaskClaiming', () => { } test('emits an event when a task is succesfully by scheduling', async () => { - const { taskManagerId, runAt, taskClaiming } = instantiateStoreWithMockedApiResponses(); + const taskDefs = new TaskTypeDictionary(taskManagerLogger); + taskDefs.registerTaskDefinitions({ + foo: { + title: 'foo', + createTaskRunner: jest.fn(), + }, + bar: { + title: 'bar', + createTaskRunner: jest.fn(), + }, + }); + + const { taskManagerId, runAt, taskClaiming } = instantiateStoreWithMockedApiResponses({ + definitions: taskDefs, + }); const promise = taskClaiming.events .pipe( @@ -1854,7 +1916,8 @@ describe('TaskClaiming', () => { retryAt: null, scheduledAt: new Date(), traceparent: 'newParent', - }) + }), + event?.timing ) ); }); diff --git a/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.ts b/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.ts index b2751803e8dc3..dce4bf66e57db 100644 --- a/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.ts +++ b/x-pack/plugins/task_manager/server/task_claimers/strategy_mget.ts @@ -23,15 +23,11 @@ import { TaskClaimerOpts, ClaimOwnershipResult, getEmptyClaimOwnershipResult, - isTaskTypeExcluded, + getExcludedTaskTypes, } from '.'; import { ConcreteTaskInstance, TaskStatus, ConcreteTaskInstanceVersion, TaskCost } from '../task'; import { TASK_MANAGER_TRANSACTION_TYPE } from '../task_running'; -import { - isLimited, - TASK_MANAGER_MARK_AS_CLAIMED, - TaskClaimingBatches, -} from '../queries/task_claiming'; +import { TASK_MANAGER_MARK_AS_CLAIMED } from '../queries/task_claiming'; import { TaskClaim, asTaskClaimEvent, startTaskTimer } from '../task_events'; import { shouldBeOneOf, mustBeAllOf, filterDownBy, matchesClauses } from '../queries/query_clauses'; @@ -48,6 +44,7 @@ import { import { TaskStore, SearchOpts } from '../task_store'; import { isOk, asOk } from '../lib/result_type'; +import { selectTasksByCapacity } from './lib/task_selector_by_capacity'; import { TaskPartitioner } from '../lib/task_partitioner'; interface OwnershipClaimingOpts { @@ -55,7 +52,8 @@ interface OwnershipClaimingOpts { size: number; taskTypes: Set; removedTypes: Set; - excludedTaskTypes: string[]; + getCapacity: (taskType?: string | undefined) => number; + excludedTaskTypePatterns: string[]; taskStore: TaskStore; events$: Subject; definitions: TaskTypeDictionary; @@ -113,11 +111,12 @@ async function claimAvailableTasks(opts: TaskClaimerOpts): Promise { - const searchedTypes = Array.from(taskTypes) - .concat(Array.from(removedTypes)) - .filter((type) => !isTaskTypeExcluded(excludedTaskTypes, type)); - const queryForScheduledTasks = mustBeAllOf( - // Task must be enabled - EnabledTask, - // a task type that's not excluded (may be removed or not) - OneOfTaskTypes('task.taskType', searchedTypes), - // Either a task with idle status and runAt <= now or - // status running or claiming with a retryAt <= now. - shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt), - // must have a status that isn't 'unrecognized' - RecognizedTask - ); + const excludedTaskTypes = new Set(getExcludedTaskTypes(definitions, excludedTaskTypePatterns)); + const claimPartitions = buildClaimPartitions({ + types: taskTypes, + excludedTaskTypes, + removedTypes, + getCapacity, + definitions, + }); const partitions = await taskPartitioner.getPartitions(); const sort: NonNullable = getClaimSort(definitions); - const query = matchesClauses( - queryForScheduledTasks, - filterDownBy(InactiveTasks), - tasksWithPartitions(partitions) - ); + const searches: SearchOpts[] = []; + + // not handling removed types yet + + // add search for unlimited types + if (claimPartitions.unlimitedTypes.length > 0) { + const queryForUnlimitedTasks = mustBeAllOf( + // Task must be enabled + EnabledTask, + // a task type that's not excluded (may be removed or not) + OneOfTaskTypes('task.taskType', claimPartitions.unlimitedTypes), + // Either a task with idle status and runAt <= now or + // status running or claiming with a retryAt <= now. + shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt), + // must have a status that isn't 'unrecognized' + RecognizedTask + ); + + const queryUnlimitedTasks = matchesClauses( + queryForUnlimitedTasks, + filterDownBy(InactiveTasks), + tasksWithPartitions(partitions) + ); + searches.push({ + query: queryUnlimitedTasks, + sort, // note: we could optimize this to not sort on priority, for this case + size, + seq_no_primary_term: true, + }); + } - return await taskStore.fetch( - { + // add searches for limited types + for (const [type, capacity] of claimPartitions.limitedTypes) { + const queryForLimitedTasks = mustBeAllOf( + // Task must be enabled + EnabledTask, + // Specific task type + OneOfTaskTypes('task.taskType', [type]), + // Either a task with idle status and runAt <= now or + // status running or claiming with a retryAt <= now. + shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt), + // must have a status that isn't 'unrecognized' + RecognizedTask + ); + + const query = matchesClauses( + queryForLimitedTasks, + filterDownBy(InactiveTasks), + tasksWithPartitions(partitions) + ); + searches.push({ query, sort, - size, + size: capacity * SIZE_MULTIPLIER_FOR_TASK_FETCH, seq_no_primary_term: true, - }, - // limit the response size - true - ); + }); + } + + return await taskStore.msearch(searches); } -function applyLimitedConcurrency( - tasks: ConcreteTaskInstance[], - batches: TaskClaimingBatches -): ConcreteTaskInstance[] { - // create a map of task type - concurrency - const limitedBatches = batches.filter(isLimited); - const limitedMap = new Map(); - for (const limitedBatch of limitedBatches) { - const { tasksTypes, concurrency } = limitedBatch; - limitedMap.set(tasksTypes, concurrency); - } +interface ClaimPartitions { + removedTypes: string[]; + unlimitedTypes: string[]; + limitedTypes: Map; +} + +interface BuildClaimPartitionsOpts { + types: Set; + excludedTaskTypes: Set; + removedTypes: Set; + getCapacity: (taskType?: string) => number; + definitions: TaskTypeDictionary; +} + +function buildClaimPartitions(opts: BuildClaimPartitionsOpts): ClaimPartitions { + const result: ClaimPartitions = { + removedTypes: [], + unlimitedTypes: [], + limitedTypes: new Map(), + }; + + const { types, excludedTaskTypes, removedTypes, getCapacity, definitions } = opts; + for (const type of types) { + const definition = definitions.get(type); + if (definition == null) continue; + + if (excludedTaskTypes.has(type)) continue; + + if (removedTypes.has(type)) { + result.removedTypes.push(type); + continue; + } - // apply the limited concurrency - const result: ConcreteTaskInstance[] = []; - for (const task of tasks) { - const concurrency = limitedMap.get(task.taskType); - if (concurrency == null) { - result.push(task); + if (definition.maxConcurrency == null) { + result.unlimitedTypes.push(definition.type); continue; } - if (concurrency > 0) { - result.push(task); - limitedMap.set(task.taskType, concurrency - 1); + const capacity = getCapacity(definition.type) / definition.cost; + if (capacity !== 0) { + result.limitedTypes.set(definition.type, capacity); } } diff --git a/x-pack/plugins/task_manager/server/task_store.mock.ts b/x-pack/plugins/task_manager/server/task_store.mock.ts index c15518eaed510..7cf051f406532 100644 --- a/x-pack/plugins/task_manager/server/task_store.mock.ts +++ b/x-pack/plugins/task_manager/server/task_store.mock.ts @@ -33,6 +33,8 @@ export const taskStoreMock = { bulkGet: jest.fn(), bulkGetVersions: jest.fn(), getDocVersions: jest.fn(), + search: jest.fn(), + msearch: jest.fn(), index, taskManagerId, } as unknown as jest.Mocked; diff --git a/x-pack/plugins/task_manager/server/task_store.test.ts b/x-pack/plugins/task_manager/server/task_store.test.ts index 80c1f46f53e4d..19f2861b0ed16 100644 --- a/x-pack/plugins/task_manager/server/task_store.test.ts +++ b/x-pack/plugins/task_manager/server/task_store.test.ts @@ -360,6 +360,141 @@ describe('TaskStore', () => { }); }); + describe('msearch', () => { + let store: TaskStore; + let esClient: ReturnType['asInternalUser']; + let childEsClient: ReturnType< + typeof elasticsearchServiceMock.createClusterClient + >['asInternalUser']; + + beforeAll(() => { + esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + childEsClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.child.mockReturnValue(childEsClient as unknown as Client); + store = new TaskStore({ + logger: mockLogger(), + index: 'tasky', + taskManagerId: '', + serializer, + esClient, + definitions: taskDefinitions, + savedObjectsRepository: savedObjectsClient, + adHocTaskCounter, + allowReadingInvalidState: false, + requestTimeouts: { + update_by_query: 1000, + }, + }); + }); + + async function testMsearch( + optsArray: SearchOpts[], + hitsArray: Array> = [] + ) { + childEsClient.msearch.mockResponse({ + took: 0, + responses: hitsArray.map((hits) => ({ + hits, + took: 0, + _shards: { + failed: 0, + successful: 1, + total: 1, + }, + timed_out: false, + status: 200, + })), + }); + + const result = await store.msearch(optsArray); + + expect(childEsClient.msearch).toHaveBeenCalledTimes(1); + + return { + result, + args: childEsClient.msearch.mock.calls[0][0], + }; + } + + test('empty call filters by type, sorts by runAt and id', async () => { + const { args } = await testMsearch([{}], []); + expect(args).toMatchObject({ + index: 'tasky', + body: [ + {}, + { + sort: [{ 'task.runAt': 'asc' }], + query: { term: { type: 'task' } }, + }, + ], + }); + }); + + test('allows multiple custom queries', async () => { + const { args } = await testMsearch( + [ + { + query: { + term: { 'task.taskType': 'foo' }, + }, + }, + { + query: { + term: { 'task.taskType': 'bar' }, + }, + }, + ], + [] + ); + + expect(args).toMatchObject({ + body: [ + {}, + { + query: { + bool: { + must: [{ term: { type: 'task' } }, { term: { 'task.taskType': 'foo' } }], + }, + }, + }, + {}, + { + query: { + bool: { + must: [{ term: { type: 'task' } }, { term: { 'task.taskType': 'bar' } }], + }, + }, + }, + ], + }); + }); + + test('pushes error from call cluster to errors$', async () => { + const firstErrorPromise = store.errors$.pipe(first()).toPromise(); + childEsClient.msearch.mockResponse({ + took: 0, + responses: [ + { + took: 0, + _shards: { + failed: 0, + successful: 1, + total: 1, + }, + timed_out: false, + status: 429, + }, + ], + } as estypes.MsearchResponse); + await expect(store.msearch([{}])).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected status code from taskStore::msearch: 429"` + ); + expect(await firstErrorPromise).toMatchInlineSnapshot( + `[Error: Unexpected status code from taskStore::msearch: 429]` + ); + }); + }); + describe('aggregate', () => { let store: TaskStore; let esClient: ReturnType['asInternalUser']; diff --git a/x-pack/plugins/task_manager/server/task_store.ts b/x-pack/plugins/task_manager/server/task_store.ts index 9b58d7bc3c18b..12a1f256c585b 100644 --- a/x-pack/plugins/task_manager/server/task_store.ts +++ b/x-pack/plugins/task_manager/server/task_store.ts @@ -41,6 +41,7 @@ import { import { TaskTypeDictionary } from './task_type_dictionary'; import { AdHocTaskCounter } from './lib/adhoc_task_counter'; import { TaskValidator } from './task_validator'; +import { claimSort } from './queries/mark_available_tasks_as_claimed'; import { MAX_PARTITIONS } from './lib/task_partitioner'; export interface StoreOpts { @@ -504,6 +505,41 @@ export class TaskStore { } } + // like search(), only runs multiple searches in parallel returning the combined results + async msearch(opts: SearchOpts[] = []): Promise { + const queries = opts.map(({ sort = [{ 'task.runAt': 'asc' }], ...opt }) => + ensureQueryOnlyReturnsTaskObjects({ sort, ...opt }) + ); + const body = queries.flatMap((query) => [{}, query]); + + const result = await this.esClientWithoutRetries.msearch({ + index: this.index, + ignore_unavailable: true, + body, + }); + const { responses } = result; + + const versionMap = this.createVersionMap([]); + let allTasks = new Array(); + + for (const response of responses) { + if (response.status !== 200) { + const err = new Error(`Unexpected status code from taskStore::msearch: ${response.status}`); + this.errors$.next(err); + throw err; + } + + const { hits } = response as estypes.MsearchMultiSearchItem; + const { hits: tasks } = hits; + this.addTasksToVersionMap(versionMap, tasks); + allTasks = allTasks.concat(this.filterTasks(tasks)); + } + + const allSortedTasks = claimSort(this.definitions, allTasks); + + return { docs: allSortedTasks, versionMap }; + } + private async search( opts: SearchOpts = {}, limitResponse: boolean = false @@ -522,27 +558,9 @@ export class TaskStore { hits: { hits: tasks }, } = result; - const versionMap = new Map(); - for (const task of tasks) { - if (task._seq_no == null || task._primary_term == null) continue; - - const esId = task._id!.startsWith('task:') ? task._id!.slice(5) : task._id!; - versionMap.set(esId, { - esId: task._id!, - seqNo: task._seq_no, - primaryTerm: task._primary_term, - }); - } - + const versionMap = this.createVersionMap(tasks); return { - docs: tasks - // @ts-expect-error @elastic/elasticsearch _source is optional - .filter((doc) => this.serializer.isRawSavedObject(doc)) - // @ts-expect-error @elastic/elasticsearch _source is optional - .map((doc) => this.serializer.rawToSavedObject(doc)) - .map((doc) => omit(doc, 'namespace') as SavedObject) - .map((doc) => savedObjectToConcreteTaskInstance(doc)) - .filter((doc): doc is ConcreteTaskInstance => !!doc), + docs: this.filterTasks(tasks), versionMap, }; } catch (e) { @@ -551,6 +569,45 @@ export class TaskStore { } } + private filterTasks( + tasks: Array> + ): ConcreteTaskInstance[] { + return ( + tasks + // @ts-expect-error @elastic/elasticsearch _source is optional + .filter((doc) => this.serializer.isRawSavedObject(doc)) + // @ts-expect-error @elastic/elasticsearch _source is optional + .map((doc) => this.serializer.rawToSavedObject(doc)) + .map((doc) => omit(doc, 'namespace') as SavedObject) + .map((doc) => savedObjectToConcreteTaskInstance(doc)) + .filter((doc): doc is ConcreteTaskInstance => !!doc) + ); + } + + private addTasksToVersionMap( + versionMap: Map, + tasks: Array> + ): void { + for (const task of tasks) { + if (task._id == null || task._seq_no == null || task._primary_term == null) continue; + + const esId = task._id.startsWith('task:') ? task._id.slice(5) : task._id; + versionMap.set(esId, { + esId: task._id, + seqNo: task._seq_no, + primaryTerm: task._primary_term, + }); + } + } + + private createVersionMap( + tasks: Array> + ): Map { + const versionMap = new Map(); + this.addTasksToVersionMap(versionMap, tasks); + return versionMap; + } + public async aggregate({ aggs, query, From 5314f3de5e51998b12501d5fa4fc6e3cdfa0ef3c Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 26 Aug 2024 20:05:40 +0100 Subject: [PATCH 02/38] skip flaky suite (#191260) --- .../context_awareness/extensions/_get_default_app_state.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/extensions/_get_default_app_state.ts b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/extensions/_get_default_app_state.ts index 7203793330590..1755d386d4554 100644 --- a/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/extensions/_get_default_app_state.ts +++ b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/extensions/_get_default_app_state.ts @@ -132,7 +132,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('data view mode', () => { + // FLAKY: https://github.com/elastic/kibana/issues/191260 + describe.skip('data view mode', () => { it('should render default columns and row height', async () => { await PageObjects.common.navigateToActualUrl('discover', undefined, { ensureCurrentUrl: false, From 6f49730190e961d50320ce3331bc4325886c8168 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 26 Aug 2024 20:08:00 +0100 Subject: [PATCH 03/38] skip flaky suite (#191144) --- .../pages/cis_integrations/cspm/cis_integration_gcp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts index 66bd58ea4967e..0b6c98f4b77d8 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts @@ -177,7 +177,8 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('CIS_GCP Single', () => { + // FLAKY: https://github.com/elastic/kibana/issues/191144 + describe.skip('CIS_GCP Single', () => { it('Post Installation Google Cloud Shell modal pops up after user clicks on Save button when adding integration, when there are no Project ID, it should use default value', async () => { await cisIntegration.clickOptionButton(CIS_GCP_OPTION_TEST_ID); await cisIntegration.clickOptionButton(GCP_SINGLE_ACCOUNT_TEST_ID); From a7d6a03c072fc7faef8ffd25ae4c3fbbb5821c52 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 26 Aug 2024 20:09:46 +0100 Subject: [PATCH 04/38] skip flaky suite (#190779) --- .../pages/cis_integrations/cspm/cis_integration_gcp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts index 0b6c98f4b77d8..6af6fdda3fccd 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts @@ -131,7 +131,8 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('CIS_GCP Organization Credentials File', () => { + // FLAKY: https://github.com/elastic/kibana/issues/190779 + describe.skip('CIS_GCP Organization Credentials File', () => { it('CIS_GCP Organization Credentials File workflow', async () => { const projectName = 'PRJ_NAME_TEST'; const credentialFileName = 'CRED_FILE_TEST_NAME'; From dbc4a29a9e50bc4b5732874c60fb75ba36c7ea88 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 26 Aug 2024 20:11:36 +0100 Subject: [PATCH 05/38] skip flaky suite (#191027) --- .../pages/cis_integrations/cspm/cis_integration_gcp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts index 6af6fdda3fccd..698c2db91938e 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts @@ -36,7 +36,8 @@ export default function (providerContext: FtrProviderContext) { await cisIntegration.navigateToAddIntegrationCspmPage(); }); - describe('CIS_GCP Organization', () => { + // FLAKY: https://github.com/elastic/kibana/issues/191027 + describe.skip('CIS_GCP Organization', () => { it('Switch between Manual and Google cloud shell', async () => { await cisIntegration.clickOptionButton(CIS_GCP_OPTION_TEST_ID); await cisIntegration.clickOptionButton(GCP_ORGANIZATION_TEST_ID); From 9ea2adb7aebccfcc5dd9db1a41f820397166c276 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 26 Aug 2024 20:17:30 +0100 Subject: [PATCH 06/38] skip flaky suite (#190637) --- .../tests/feature_controls/settings_security.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts index cea40d3ad10ce..7c2262008d8a2 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts @@ -20,7 +20,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const toasts = getService('toasts'); describe('ai assistant management privileges', () => { - describe('all privileges', () => { + // FLAKY: https://github.com/elastic/kibana/issues/190637 + describe.skip('all privileges', () => { before(async () => { await createAndLoginUserWithCustomRole(getPageObjects, getService, { // we need all these privileges to view and modify Obs AI Assistant settings view From 486df8cf5e85762531099589c2af360ab78da9fe Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Mon, 26 Aug 2024 14:44:29 -0500 Subject: [PATCH 07/38] [Search][Onboarding] Empty State page endpoints (#191229) ## Summary This PR introduces two endpoints for the `search_indices` plugin that will be used by the start (empty state) page to determine if the user has an indices and what their permissions are. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/search_indices/common/index.ts | 2 + x-pack/plugins/search_indices/common/types.ts | 17 ++ .../search_indices/server/lib/status.test.ts | 231 ++++++++++++++++++ .../search_indices/server/lib/status.ts | 70 ++++++ .../plugins/search_indices/server/plugin.ts | 2 +- .../search_indices/server/routes/index.ts | 7 +- .../search_indices/server/routes/status.ts | 53 ++++ .../server/utils/index_utils.test.ts | 109 +++++++++ .../server/utils/index_utils.ts | 19 ++ x-pack/plugins/search_indices/tsconfig.json | 2 + .../search/config.feature_flags.ts | 5 +- .../test_suites/search/index.feature_flags.ts | 1 + .../search/search_indices/index.ts | 14 ++ .../search/search_indices/status.ts | 80 ++++++ .../search/config.feature_flags.ts | 1 + .../test_suites/search/elasticsearch_start.ts | 12 + .../test_suites/search/index.feature_flags.ts | 1 + 17 files changed, 623 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/search_indices/common/types.ts create mode 100644 x-pack/plugins/search_indices/server/lib/status.test.ts create mode 100644 x-pack/plugins/search_indices/server/lib/status.ts create mode 100644 x-pack/plugins/search_indices/server/routes/status.ts create mode 100644 x-pack/plugins/search_indices/server/utils/index_utils.test.ts create mode 100644 x-pack/plugins/search_indices/server/utils/index_utils.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/search/search_indices/index.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts create mode 100644 x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts diff --git a/x-pack/plugins/search_indices/common/index.ts b/x-pack/plugins/search_indices/common/index.ts index a0e7d3fe35e68..f2b3e62577e4f 100644 --- a/x-pack/plugins/search_indices/common/index.ts +++ b/x-pack/plugins/search_indices/common/index.ts @@ -7,3 +7,5 @@ export const PLUGIN_ID = 'searchIndices'; export const PLUGIN_NAME = 'searchIndices'; + +export type { IndicesStatusResponse, UserStartPrivilegesResponse } from './types'; diff --git a/x-pack/plugins/search_indices/common/types.ts b/x-pack/plugins/search_indices/common/types.ts new file mode 100644 index 0000000000000..8c7af3889a5a2 --- /dev/null +++ b/x-pack/plugins/search_indices/common/types.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 interface IndicesStatusResponse { + indexNames: string[]; +} + +export interface UserStartPrivilegesResponse { + privileges: { + canCreateApiKeys: boolean; + canCreateIndex: boolean; + }; +} diff --git a/x-pack/plugins/search_indices/server/lib/status.test.ts b/x-pack/plugins/search_indices/server/lib/status.test.ts new file mode 100644 index 0000000000000..ff5a8fc1eadd5 --- /dev/null +++ b/x-pack/plugins/search_indices/server/lib/status.test.ts @@ -0,0 +1,231 @@ +/* + * 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 type { + IndicesGetResponse, + SecurityHasPrivilegesResponse, +} from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { Logger } from '@kbn/logging'; +import { fetchIndicesStatus, fetchUserStartPrivileges } from './status'; + +const mockLogger = { + warn: jest.fn(), + error: jest.fn(), +}; +const logger: Logger = mockLogger as unknown as Logger; + +const mockClient = { + indices: { + get: jest.fn(), + }, + security: { + hasPrivileges: jest.fn(), + }, +}; +const client = mockClient as unknown as ElasticsearchClient; + +describe('status api lib', function () { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('fetchIndicesStatus', function () { + it('should return results from get', async () => { + const mockResult: IndicesGetResponse = {}; + mockClient.indices.get.mockResolvedValue(mockResult); + + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ indexNames: [] }); + expect(mockClient.indices.get).toHaveBeenCalledTimes(1); + expect(mockClient.indices.get).toHaveBeenCalledWith({ + expand_wildcards: ['open'], + features: ['settings'], + index: '*', + }); + }); + it('should return index names', async () => { + const mockResult: IndicesGetResponse = { + 'unit-test-index': { + settings: {}, + }, + }; + mockClient.indices.get.mockResolvedValue(mockResult); + + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ + indexNames: ['unit-test-index'], + }); + }); + it('should not return hidden indices', async () => { + const mockResult: IndicesGetResponse = { + 'unit-test-index': { + settings: {}, + }, + 'hidden-index': { + settings: { + index: { + hidden: true, + }, + }, + }, + }; + mockClient.indices.get.mockResolvedValue(mockResult); + + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ + indexNames: ['unit-test-index'], + }); + + mockResult['hidden-index']!.settings!.index!.hidden = 'true'; + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ + indexNames: ['unit-test-index'], + }); + }); + it('should not return closed indices', async () => { + const mockResult: IndicesGetResponse = { + 'unit-test-index': { + settings: {}, + }, + 'closed-index': { + settings: { + index: { + verified_before_close: true, + }, + }, + }, + }; + mockClient.indices.get.mockResolvedValue(mockResult); + + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ + indexNames: ['unit-test-index'], + }); + + mockResult['closed-index']!.settings!.index!.verified_before_close = 'true'; + await expect(fetchIndicesStatus(client, logger)).resolves.toEqual({ + indexNames: ['unit-test-index'], + }); + }); + it('should raise exceptions', async () => { + const error = new Error('boom'); + mockClient.indices.get.mockRejectedValue(error); + + await expect(fetchIndicesStatus(client, logger)).rejects.toThrow(error); + }); + }); + + describe('fetchUserStartPrivileges', function () { + it('should return privileges true', async () => { + const result: SecurityHasPrivilegesResponse = { + application: {}, + cluster: { + manage_api_key: true, + }, + has_all_requested: true, + index: { + 'test-index-name': { + create_index: true, + }, + }, + username: 'unit-test', + }; + mockClient.security.hasPrivileges.mockResolvedValue(result); + + await expect(fetchUserStartPrivileges(client, logger)).resolves.toEqual({ + privileges: { + canCreateIndex: true, + canCreateApiKeys: true, + }, + }); + + expect(mockClient.security.hasPrivileges).toHaveBeenCalledTimes(1); + expect(mockClient.security.hasPrivileges).toHaveBeenCalledWith({ + cluster: ['manage_api_key'], + index: [ + { + names: ['test-index-name'], + privileges: ['create_index'], + }, + ], + }); + }); + it('should return privileges false', async () => { + const result: SecurityHasPrivilegesResponse = { + application: {}, + cluster: { + manage_api_key: false, + }, + has_all_requested: false, + index: { + 'test-index-name': { + create_index: false, + }, + }, + username: 'unit-test', + }; + mockClient.security.hasPrivileges.mockResolvedValue(result); + + await expect(fetchUserStartPrivileges(client, logger)).resolves.toEqual({ + privileges: { + canCreateIndex: false, + canCreateApiKeys: false, + }, + }); + }); + it('should return mixed privileges', async () => { + const result: SecurityHasPrivilegesResponse = { + application: {}, + cluster: { + manage_api_key: false, + }, + has_all_requested: false, + index: { + 'test-index-name': { + create_index: true, + }, + }, + username: 'unit-test', + }; + mockClient.security.hasPrivileges.mockResolvedValue(result); + + await expect(fetchUserStartPrivileges(client, logger)).resolves.toEqual({ + privileges: { + canCreateIndex: true, + canCreateApiKeys: false, + }, + }); + }); + it('should handle malformed responses', async () => { + const result: SecurityHasPrivilegesResponse = { + application: {}, + cluster: {}, + has_all_requested: true, + index: { + 'test-index-name': { + create_index: true, + }, + }, + username: 'unit-test', + }; + mockClient.security.hasPrivileges.mockResolvedValue(result); + + await expect(fetchUserStartPrivileges(client, logger)).resolves.toEqual({ + privileges: { + canCreateIndex: true, + canCreateApiKeys: false, + }, + }); + }); + it('should default privileges on exceptions', async () => { + mockClient.security.hasPrivileges.mockRejectedValue(new Error('Boom!!')); + + await expect(fetchUserStartPrivileges(client, logger)).resolves.toEqual({ + privileges: { + canCreateIndex: false, + canCreateApiKeys: false, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/search_indices/server/lib/status.ts b/x-pack/plugins/search_indices/server/lib/status.ts new file mode 100644 index 0000000000000..752e897ab1707 --- /dev/null +++ b/x-pack/plugins/search_indices/server/lib/status.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { Logger } from '@kbn/logging'; + +import type { IndicesStatusResponse, UserStartPrivilegesResponse } from '../../common/types'; + +import { isHidden, isClosed } from '../utils/index_utils'; + +export async function fetchIndicesStatus( + client: ElasticsearchClient, + logger: Logger +): Promise { + const indexMatches = await client.indices.get({ + expand_wildcards: ['open'], + // for better performance only compute settings of indices but not mappings + features: ['settings'], + index: '*', + }); + + const indexNames = Object.keys(indexMatches).filter( + (indexName) => + indexMatches[indexName] && + !isHidden(indexMatches[indexName]) && + !isClosed(indexMatches[indexName]) + ); + + return { + indexNames, + }; +} + +export async function fetchUserStartPrivileges( + client: ElasticsearchClient, + logger: Logger, + indexName: string = 'test-index-name' +): Promise { + try { + const securityCheck = await client.security.hasPrivileges({ + cluster: ['manage_api_key'], + index: [ + { + names: [indexName], + privileges: ['create_index'], + }, + ], + }); + + return { + privileges: { + canCreateIndex: securityCheck?.index?.[indexName]?.create_index ?? false, + canCreateApiKeys: securityCheck?.cluster?.manage_api_key ?? false, + }, + }; + } catch (e) { + logger.error(`Error checking user privileges for searchIndices elasticsearch start`); + logger.error(e); + return { + privileges: { + canCreateIndex: false, + canCreateApiKeys: false, + }, + }; + } +} diff --git a/x-pack/plugins/search_indices/server/plugin.ts b/x-pack/plugins/search_indices/server/plugin.ts index 666e49016f551..f0adbb112356e 100644 --- a/x-pack/plugins/search_indices/server/plugin.ts +++ b/x-pack/plugins/search_indices/server/plugin.ts @@ -31,7 +31,7 @@ export class SearchIndicesPlugin const router = core.http.createRouter(); // Register server side APIs - defineRoutes(router); + defineRoutes(router, this.logger); return {}; } diff --git a/x-pack/plugins/search_indices/server/routes/index.ts b/x-pack/plugins/search_indices/server/routes/index.ts index c98be5b6a4490..03cb1371870cb 100644 --- a/x-pack/plugins/search_indices/server/routes/index.ts +++ b/x-pack/plugins/search_indices/server/routes/index.ts @@ -6,5 +6,10 @@ */ import type { IRouter } from '@kbn/core/server'; +import type { Logger } from '@kbn/logging'; -export function defineRoutes(router: IRouter) {} +import { registerStatusRoutes } from './status'; + +export function defineRoutes(router: IRouter, logger: Logger) { + registerStatusRoutes(router, logger); +} diff --git a/x-pack/plugins/search_indices/server/routes/status.ts b/x-pack/plugins/search_indices/server/routes/status.ts new file mode 100644 index 0000000000000..ab3a426510e6e --- /dev/null +++ b/x-pack/plugins/search_indices/server/routes/status.ts @@ -0,0 +1,53 @@ +/* + * 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 type { IRouter } from '@kbn/core/server'; +import type { Logger } from '@kbn/logging'; + +import { fetchIndicesStatus, fetchUserStartPrivileges } from '../lib/status'; + +export function registerStatusRoutes(router: IRouter, logger: Logger) { + router.get( + { + path: '/internal/search_indices/status', + validate: {}, + options: { + access: 'internal', + }, + }, + async (context, _request, response) => { + const core = await context.core; + const client = core.elasticsearch.client.asCurrentUser; + const body = await fetchIndicesStatus(client, logger); + + return response.ok({ + body, + headers: { 'content-type': 'application/json' }, + }); + } + ); + + router.get( + { + path: '/internal/search_indices/start_privileges', + validate: {}, + options: { + access: 'internal', + }, + }, + async (context, _request, response) => { + const core = await context.core; + const client = core.elasticsearch.client.asCurrentUser; + const body = await fetchUserStartPrivileges(client, logger); + + return response.ok({ + body, + headers: { 'content-type': 'application/json' }, + }); + } + ); +} diff --git a/x-pack/plugins/search_indices/server/utils/index_utils.test.ts b/x-pack/plugins/search_indices/server/utils/index_utils.test.ts new file mode 100644 index 0000000000000..95860468e5fcf --- /dev/null +++ b/x-pack/plugins/search_indices/server/utils/index_utils.test.ts @@ -0,0 +1,109 @@ +/* + * 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 { isClosed, isHidden } from './index_utils'; + +describe('index utils', function () { + describe('isClosed', function () { + it('handles boolean values', () => { + expect( + isClosed({ + settings: { + index: { + verified_before_close: true, + }, + }, + }) + ).toBe(true); + expect( + isClosed({ + settings: { + index: { + verified_before_close: false, + }, + }, + }) + ).toBe(false); + }); + it('handles string values', () => { + expect( + isClosed({ + settings: { + index: { + verified_before_close: 'true', + }, + }, + }) + ).toBe(true); + expect( + isClosed({ + settings: { + index: { + verified_before_close: 'false', + }, + }, + }) + ).toBe(false); + }); + it('handles undefined index settings', () => { + expect( + isClosed({ + settings: {}, + }) + ).toBe(false); + }); + }); + describe('isHidden', function () { + it('handles boolean values', () => { + expect( + isHidden({ + settings: { + index: { + hidden: true, + }, + }, + }) + ).toBe(true); + expect( + isHidden({ + settings: { + index: { + hidden: false, + }, + }, + }) + ).toBe(false); + }); + it('handles string values', () => { + expect( + isHidden({ + settings: { + index: { + hidden: 'true', + }, + }, + }) + ).toBe(true); + expect( + isHidden({ + settings: { + index: { + hidden: 'false', + }, + }, + }) + ).toBe(false); + }); + it('handles undefined index settings', () => { + expect( + isHidden({ + settings: {}, + }) + ).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/search_indices/server/utils/index_utils.ts b/x-pack/plugins/search_indices/server/utils/index_utils.ts new file mode 100644 index 0000000000000..d0b47b303679e --- /dev/null +++ b/x-pack/plugins/search_indices/server/utils/index_utils.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { IndicesIndexState } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +export function isHidden(index: IndicesIndexState): boolean { + return index.settings?.index?.hidden === true || index.settings?.index?.hidden === 'true'; +} + +export function isClosed(index: IndicesIndexState): boolean { + return ( + index.settings?.index?.verified_before_close === true || + index.settings?.index?.verified_before_close === 'true' + ); +} diff --git a/x-pack/plugins/search_indices/tsconfig.json b/x-pack/plugins/search_indices/tsconfig.json index 48969cf7142bb..406b9de2400ce 100644 --- a/x-pack/plugins/search_indices/tsconfig.json +++ b/x-pack/plugins/search_indices/tsconfig.json @@ -14,6 +14,8 @@ "@kbn/core", "@kbn/navigation-plugin", "@kbn/config-schema", + "@kbn/core-elasticsearch-server", + "@kbn/logging", ], "exclude": [ "target/**/*", diff --git a/x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts b/x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts index 87064adf39d9f..3126619ae60ee 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts @@ -18,7 +18,10 @@ export default createTestConfig({ }, suiteTags: { exclude: ['skipSvlSearch'] }, // add feature flags - kbnServerArgs: ['--xpack.security.roleManagementEnabled=true'], + kbnServerArgs: [ + '--xpack.security.roleManagementEnabled=true', + `--xpack.searchIndices.enabled=true`, // global empty state FF + ], // load tests in the index file testFiles: [require.resolve('./index.feature_flags.ts')], diff --git a/x-pack/test_serverless/api_integration/test_suites/search/index.feature_flags.ts b/x-pack/test_serverless/api_integration/test_suites/search/index.feature_flags.ts index a757df76f10f3..a4a99f1e42641 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/index.feature_flags.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/index.feature_flags.ts @@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Serverless search API - feature flags', function () { + loadTestFile(require.resolve('./search_indices')); loadTestFile(require.resolve('./platform_security')); loadTestFile(require.resolve('../common/platform_security/roles_routes_feature_flag.ts')); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/index.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/index.ts new file mode 100644 index 0000000000000..b48985faaecd5 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('search indices APIs', function () { + loadTestFile(require.resolve('./status')); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts new file mode 100644 index 0000000000000..b9e9fedbb0396 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let credentials: { Cookie: string }; + + describe('search_indices Status APIs', function () { + describe('indices status', function () { + before(async () => { + // get auth header for Viewer role + credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('developer'); + }); + it('returns list of index names', async () => { + const { body } = await supertestWithoutAuth + .get('/internal/search_indices/status') + .set(svlCommonApi.getInternalRequestHeader()) + .set(credentials) + .expect(200); + + expect(body.indexNames).toBeDefined(); + expect(Array.isArray(body.indexNames)).toBe(true); + }); + }); + describe('user privileges', function () { + // GET /internal/search_indices/start_privileges + describe('developer', function () { + before(async () => { + // get auth header for Viewer role + credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('developer'); + }); + + it('returns expected privileges', async () => { + const { body } = await supertestWithoutAuth + .get('/internal/search_indices/start_privileges') + .set(svlCommonApi.getInternalRequestHeader()) + .set(credentials) + .expect(200); + + expect(body).toEqual({ + privileges: { + canCreateApiKeys: true, + canCreateIndex: true, + }, + }); + }); + }); + describe('viewer', function () { + before(async () => { + // get auth header for Viewer role + credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('viewer'); + }); + + it('returns expected privileges', async () => { + const { body } = await supertestWithoutAuth + .get('/internal/search_indices/start_privileges') + .set(svlCommonApi.getInternalRequestHeader()) + .set(credentials) + .expect(200); + + expect(body).toEqual({ + privileges: { + canCreateApiKeys: false, + canCreateIndex: false, + }, + }); + }); + }); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts b/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts index ee652f0f7eb2d..05eb6136bf008 100644 --- a/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts +++ b/x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts @@ -25,6 +25,7 @@ export default createTestConfig({ `--xpack.cloud.organization_url='/account/members'`, `--xpack.security.roleManagementEnabled=true`, `--xpack.spaces.maxSpaces=100`, // enables spaces UI capabilities + `--xpack.searchIndices.enabled=true`, // global empty state FF ], // load tests in the index file testFiles: [require.resolve('./index.feature_flags.ts')], diff --git a/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts b/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.ts new file mode 100644 index 0000000000000..5b5adf48319db --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/elasticsearch_start.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({}: FtrProviderContext) { + describe('Elasticsearch Start [Onboarding Empty State]', function () {}); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts b/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts index acf3e6f98b7db..44cd17a0c9fd3 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.feature_flags.ts @@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI - feature flags', function () { // add tests that require feature flags, defined in config.feature_flags.ts + loadTestFile(require.resolve('./elasticsearch_start.ts')); loadTestFile(require.resolve('../common/platform_security/navigation/management_nav_cards.ts')); loadTestFile(require.resolve('../common/platform_security/roles.ts')); loadTestFile(require.resolve('../common/spaces/spaces_selection_enabled.ts')); From dc7e3ec999176bdaf85bc0fbef8799f55f5b7cf8 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Mon, 26 Aug 2024 13:08:32 -0700 Subject: [PATCH 08/38] [EuiProvider / Functional tests] Check for EuiProvider Dev Warning (#189018) ## Summary Follows https://github.com/elastic/kibana/pull/184608 Closes https://github.com/elastic/kibana-team/issues/805 ![image](https://github.com/user-attachments/assets/eaee5b81-c1e9-4e81-9018-db57652236dc) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + .../writing_stable_functional_tests.mdx | 4 ++ package.json | 1 + .../src/chrome_service.tsx | 15 ++++++- .../services/browser.ts | 21 +++++++++ .../services/remote/remote.ts | 36 +++++++++++++++ test/plugin_functional/config.ts | 1 + .../eui_provider_dev_warning/kibana.jsonc | 13 ++++++ .../eui_provider_dev_warning/package.json | 14 ++++++ .../public/application.tsx | 38 ++++++++++++++++ .../eui_provider_dev_warning/public/index.ts | 13 ++++++ .../eui_provider_dev_warning/public/plugin.ts | 35 +++++++++++++++ .../eui_provider_dev_warning/tsconfig.json | 18 ++++++++ .../test_suites/shared_ux/eui_provider.ts | 45 +++++++++++++++++++ .../test_suites/shared_ux/index.ts | 15 +++++++ tsconfig.base.json | 2 + yarn.lock | 4 ++ 17 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/kibana.jsonc create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/package.json create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/public/application.tsx create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/public/index.ts create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/public/plugin.ts create mode 100644 test/plugin_functional/plugins/eui_provider_dev_warning/tsconfig.json create mode 100644 test/plugin_functional/test_suites/shared_ux/eui_provider.ts create mode 100644 test/plugin_functional/test_suites/shared_ux/index.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 41b3617cc52b9..277ac73bedf0c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -425,6 +425,7 @@ src/plugins/esql_datagrid @elastic/kibana-esql packages/kbn-esql-utils @elastic/kibana-esql packages/kbn-esql-validation-autocomplete @elastic/kibana-esql examples/esql_validation_example @elastic/kibana-esql +test/plugin_functional/plugins/eui_provider_dev_warning @elastic/appex-sharedux packages/kbn-event-annotation-common @elastic/kibana-visualizations packages/kbn-event-annotation-components @elastic/kibana-visualizations src/plugins/event_annotation_listing @elastic/kibana-visualizations diff --git a/dev_docs/operations/writing_stable_functional_tests.mdx b/dev_docs/operations/writing_stable_functional_tests.mdx index 9403b9144260d..42aadf702ba92 100644 --- a/dev_docs/operations/writing_stable_functional_tests.mdx +++ b/dev_docs/operations/writing_stable_functional_tests.mdx @@ -75,6 +75,10 @@ await testSubjects.existsOrFail('savedItemDetailPage') Even if you are very careful, the more UI automation you do the more likely you are to make a mistake and write a flaky test. If there is any way to do setup work for your test via the Kibana or Elasticsearch APIs rather than interacting with the UI, then take advantage of that opportunity to write less UI automation. +## Incorrect usage of EUI components in React code will cause a functional test failure + +For EUI to support theming and internationalization, EUI components in your React application must be wrapped in `EuiProvider` (more preferably, use the `KibanaRenderContextProvider` wrapper). The functional test runner treats EUI as a first-class citizen and will throw an error when incorrect usage of EUI is detected. However, experiencing this type of failure in a test run is unlikely: in dev mode, a toast message alerts developers of incorrect EUI usage in real-time. + ## Do you really need a functional test for this? Once you've invested a lot of time and energy into figuring out how to write functional tests well it can be tempting to use them for all sorts of things which might not justify the cost of a functional test. Make sure that your test is validating something that couldn't be validated by a series of unit tests on a component+store+API. diff --git a/package.json b/package.json index 5ece731ab84d0..c07597726ca47 100644 --- a/package.json +++ b/package.json @@ -479,6 +479,7 @@ "@kbn/esql-utils": "link:packages/kbn-esql-utils", "@kbn/esql-validation-autocomplete": "link:packages/kbn-esql-validation-autocomplete", "@kbn/esql-validation-example-plugin": "link:examples/esql_validation_example", + "@kbn/eui-provider-dev-warning": "link:test/plugin_functional/plugins/eui_provider_dev_warning", "@kbn/event-annotation-common": "link:packages/kbn-event-annotation-common", "@kbn/event-annotation-components": "link:packages/kbn-event-annotation-components", "@kbn/event-annotation-listing-plugin": "link:src/plugins/event_annotation_listing", diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 5f9a17713861c..0b7f0e8afd958 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -180,14 +180,24 @@ export class ChromeService { if (isDev) { setEuiDevProviderWarning((providerError) => { const errorObject = new Error(providerError.toString()); - // show a stack trace in the console + // 1. show a stack trace in the console // eslint-disable-next-line no-console console.error(errorObject); + // 2. store error in sessionStorage so it can be detected in testing + const storedError = { + message: providerError.toString(), + stack: errorObject.stack ?? 'undefined', + pageHref: window.location.href, + pageTitle: document.title, + }; + sessionStorage.setItem('dev.euiProviderWarning', JSON.stringify(storedError)); + + // 3. error toast / popup notifications.toasts.addDanger({ title: '`EuiProvider` is missing', text: mountReactNode( -

+

), + 'data-test-subj': 'core-chrome-euiDevProviderWarning-toast', toastLifeTimeMs: 60 * 60 * 1000, // keep message visible for up to an hour }); }); diff --git a/packages/kbn-ftr-common-functional-ui-services/services/browser.ts b/packages/kbn-ftr-common-functional-ui-services/services/browser.ts index c017433446d75..8ac46821c60bf 100644 --- a/packages/kbn-ftr-common-functional-ui-services/services/browser.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/browser.ts @@ -590,6 +590,27 @@ class BrowserService extends FtrService { await this.driver.executeScript('return window.localStorage.clear();'); } + /** + * Adds a value in session storage for the focused window/frame. + * + * @return {Promise} + */ + public async getSessionStorageItem(key: string): Promise { + return await this.driver.executeScript( + `return window.sessionStorage.getItem("${key}");` + ); + } + + /** + * Removes a value in session storage for the focused window/frame. + * + * @param {string} key + * @return {Promise} + */ + public async removeSessionStorageItem(key: string): Promise { + await this.driver.executeScript('return window.sessionStorage.removeItem(arguments[0]);', key); + } + /** * Clears session storage for the focused window/frame. * diff --git a/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts index 6eb10984eeb66..a4c45e7b24e7c 100644 --- a/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts @@ -18,6 +18,16 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { const browserType: Browsers = config.get('browser.type'); type BrowserStorage = 'sessionStorage' | 'localStorage'; + const getSessionStorageItem = async (key: string) => { + try { + return await driver.executeScript(`return window.sessionStorage.getItem("${key}");`); + } catch (error) { + if (!error.message.includes(`Failed to read the 'sessionStorage' property from 'Window'`)) { + throw error; + } + } + }; + const clearBrowserStorage = async (storageType: BrowserStorage) => { try { await driver.executeScript(`window.${storageType}.clear();`); @@ -93,6 +103,32 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { lifecycle.afterTestSuite.add(async () => { await tryWebDriverCall(async () => { + // collect error message stashed in SessionStorage that indicate EuiProvider implementation error + const euiProviderWarning = await getSessionStorageItem('dev.euiProviderWarning'); + if (euiProviderWarning != null) { + let errorMessage: string; + let errorStack: string; + let pageHref: string; + let pageTitle: string; + try { + ({ + message: errorMessage, + stack: errorStack, + pageHref, + pageTitle, + } = JSON.parse(euiProviderWarning)); + } catch (error) { + throw new Error(`Found EuiProvider dev error, but the details could not be parsed`); + } + + log.error(`pageTitle: ${pageTitle}`); + log.error(`pageHref: ${pageHref}`); + log.error(`Error: ${errorMessage}`); + log.error(`Error stack: ${errorStack}`); + throw new Error(`Found EuiProvider dev error on: ${pageHref}`); + } + + // global cleanup const { width, height } = windowSizeStack.shift()!; await driver.manage().window().setRect({ width, height }); await clearBrowserStorage('sessionStorage'); diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index 3f59cc4ff3ac5..5ed34a69bae01 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -27,6 +27,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('./test_suites/data_plugin'), require.resolve('./test_suites/saved_objects_management'), require.resolve('./test_suites/saved_objects_hidden_type'), + require.resolve('./test_suites/shared_ux'), ], services: { ...functionalConfig.get('services'), diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/kibana.jsonc b/test/plugin_functional/plugins/eui_provider_dev_warning/kibana.jsonc new file mode 100644 index 0000000000000..970c25a20d596 --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/kibana.jsonc @@ -0,0 +1,13 @@ +{ + "type": "plugin", + "id": "@kbn/eui-provider-dev-warning", + "owner": "@elastic/appex-sharedux", + "plugin": { + "id": "euiProviderDevWarning", + "server": false, + "browser": true, + "configPath": [ + "eui_provider_dev_warning" + ] + } +} diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/package.json b/test/plugin_functional/plugins/eui_provider_dev_warning/package.json new file mode 100644 index 0000000000000..97def81d81579 --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/package.json @@ -0,0 +1,14 @@ +{ + "name": "@kbn/eui-provider-dev-warning", + "version": "1.0.0", + "main": "target/test/plugin_functional/plugins/eui_provider_dev_warning", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "SSPL-1.0 OR Elastic License 2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && ../../../../node_modules/.bin/tsc" + } +} diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/public/application.tsx b/test/plugin_functional/plugins/eui_provider_dev_warning/public/application.tsx new file mode 100644 index 0000000000000..64541566c26a5 --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/public/application.tsx @@ -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 React from 'react'; +import { EuiPageTemplate, EuiTitle, EuiText } from '@elastic/eui'; +import ReactDOM from 'react-dom'; +import { AppMountParameters, CoreStart } from '@kbn/core/public'; + +export const renderApp = (_core: CoreStart, { element }: AppMountParameters) => { + ReactDOM.render( + + + +

EuiProvider is missing

+
+
+ + +

Goal of this page

+
+ +

+ The goal of this page is to create a UI that attempts to render EUI React components + without wrapping the rendering tree in EuiProvider. +

+
+
+
, + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/public/index.ts b/test/plugin_functional/plugins/eui_provider_dev_warning/public/index.ts new file mode 100644 index 0000000000000..8241ab91ba378 --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/public/index.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 { EuiProviderDevWarningPlugin } from './plugin'; + +export function plugin() { + return new EuiProviderDevWarningPlugin(); +} diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/public/plugin.ts b/test/plugin_functional/plugins/eui_provider_dev_warning/public/plugin.ts new file mode 100644 index 0000000000000..a524ff6c2095c --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/public/plugin.ts @@ -0,0 +1,35 @@ +/* + * 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 { AppMountParameters, CoreSetup, Plugin } from '@kbn/core/public'; + +export class EuiProviderDevWarningPlugin + implements Plugin +{ + public setup(core: CoreSetup) { + core.application.register({ + id: 'euiProviderDevWarning', + title: 'EUI Provider Dev Warning', + async mount(params: AppMountParameters) { + const { renderApp } = await import('./application'); + const [coreStart] = await core.getStartServices(); + coreStart.chrome.docTitle.change('EuiProvider test'); + return renderApp(coreStart, params); + }, + }); + + // Return methods that should be available to other plugins + return {}; + } + + public start() {} + public stop() {} +} + +export type EuiProviderDevWarningPluginSetup = ReturnType; +export type EuiProviderDevWarningPluginStart = ReturnType; diff --git a/test/plugin_functional/plugins/eui_provider_dev_warning/tsconfig.json b/test/plugin_functional/plugins/eui_provider_dev_warning/tsconfig.json new file mode 100644 index 0000000000000..db7cf2bb2089d --- /dev/null +++ b/test/plugin_functional/plugins/eui_provider_dev_warning/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "../../../../typings/**/*" + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/core" + ] +} diff --git a/test/plugin_functional/test_suites/shared_ux/eui_provider.ts b/test/plugin_functional/test_suites/shared_ux/eui_provider.ts new file mode 100644 index 0000000000000..b378939741f34 --- /dev/null +++ b/test/plugin_functional/test_suites/shared_ux/eui_provider.ts @@ -0,0 +1,45 @@ +/* + * 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 expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getPageObjects, getService }: PluginFunctionalProviderContext) { + const PageObjects = getPageObjects(['common', 'header']); + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + describe('EUI Provider Dev Warning', () => { + it('shows error toast to developer', async () => { + const pageTitle = 'EuiProvider test - Elastic'; + + await PageObjects.common.navigateToApp('euiProviderDevWarning'); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await browser.getTitle()).eql(pageTitle); + await testSubjects.existOrFail('core-chrome-euiDevProviderWarning-toast'); + + // check that the error has been detected and stored in session storage + const euiProviderWarning = await browser.getSessionStorageItem('dev.euiProviderWarning'); + const { + message: errorMessage, + stack: errorStack, + pageHref: errorPageHref, + pageTitle: errorPageTitle, + } = JSON.parse(euiProviderWarning!); + expect(errorMessage).to.not.be.empty(); + expect(errorStack).to.not.be.empty(); + expect(errorPageHref).to.not.be.empty(); + expect(errorPageTitle).to.be(pageTitle); + }); + + after(async () => { + // clean up to ensure test suite will pass + await browser.removeSessionStorageItem('dev.euiProviderWarning'); + }); + }); +} diff --git a/test/plugin_functional/test_suites/shared_ux/index.ts b/test/plugin_functional/test_suites/shared_ux/index.ts new file mode 100644 index 0000000000000..a42a855ea4b3f --- /dev/null +++ b/test/plugin_functional/test_suites/shared_ux/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ loadTestFile }: PluginFunctionalProviderContext) { + describe('SharedUX', () => { + loadTestFile(require.resolve('./eui_provider')); + }); +} diff --git a/tsconfig.base.json b/tsconfig.base.json index b8a8baf855e88..846a51191ab72 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -844,6 +844,8 @@ "@kbn/esql-validation-autocomplete/*": ["packages/kbn-esql-validation-autocomplete/*"], "@kbn/esql-validation-example-plugin": ["examples/esql_validation_example"], "@kbn/esql-validation-example-plugin/*": ["examples/esql_validation_example/*"], + "@kbn/eui-provider-dev-warning": ["test/plugin_functional/plugins/eui_provider_dev_warning"], + "@kbn/eui-provider-dev-warning/*": ["test/plugin_functional/plugins/eui_provider_dev_warning/*"], "@kbn/event-annotation-common": ["packages/kbn-event-annotation-common"], "@kbn/event-annotation-common/*": ["packages/kbn-event-annotation-common/*"], "@kbn/event-annotation-components": ["packages/kbn-event-annotation-components"], diff --git a/yarn.lock b/yarn.lock index 2dcc9ac31d36f..127cdf45ea4ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4943,6 +4943,10 @@ version "0.0.0" uid "" +"@kbn/eui-provider-dev-warning@link:test/plugin_functional/plugins/eui_provider_dev_warning": + version "0.0.0" + uid "" + "@kbn/event-annotation-common@link:packages/kbn-event-annotation-common": version "0.0.0" uid "" From d1cc0cb93cf27584c70e3b1ccdb63a90bd0e2d6c Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Mon, 26 Aug 2024 13:25:45 -0700 Subject: [PATCH 09/38] [Fleet UI] Set flag for `traces` in Agent policy's monitoring configuration (#191139) ## Summary This PR sets the `traces` boolean flag in an Agent policy's monitoring configuration if `traces` was included in the `monitoring_enabled` array. --- .../fleet/common/types/models/agent_policy.ts | 1 + .../cloud_preconfiguration.test.ts | 1 + .../full_agent_policy.test.ts.snap | 4 + .../monitoring_permissions.test.ts.snap | 127 +++++++++++++----- .../agent_policies/full_agent_policy.test.ts | 47 ++++++- .../agent_policies/full_agent_policy.ts | 8 +- .../monitoring_permissions.test.ts | 36 +++-- .../agent_policies/monitoring_permissions.ts | 15 ++- 8 files changed, 190 insertions(+), 49 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index ac69f0c673289..e639b364343d9 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -118,6 +118,7 @@ export interface FullAgentPolicyMonitoring { enabled: boolean; metrics: boolean; logs: boolean; + traces: boolean; } export interface FullAgentPolicy { diff --git a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts index 72335f2c94f31..5ffe6b643f77d 100644 --- a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts @@ -172,6 +172,7 @@ describe('Fleet cloud preconfiguration', () => { enabled: false, logs: false, metrics: false, + traces: false, }, protection: { enabled: false, diff --git a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap index 8518e43fdaf0d..d5ae12c00a9ff 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap @@ -11,6 +11,7 @@ Object { "enabled": false, "logs": false, "metrics": false, + "traces": false, }, "protection": Object { "enabled": false, @@ -180,6 +181,7 @@ Object { "logs": false, "metrics": true, "namespace": "default", + "traces": false, "use_output": "default", }, "protection": Object { @@ -258,6 +260,7 @@ Object { "logs": false, "metrics": true, "namespace": "default", + "traces": false, "use_output": "monitoring-output-id", }, "protection": Object { @@ -336,6 +339,7 @@ Object { "logs": false, "metrics": true, "namespace": "default", + "traces": false, "use_output": "monitoring-output-id", }, "protection": Object { diff --git a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap index fc854fd3b774f..91234c443ab76 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`getMonitoringPermissions With elastic agent package installed should return default logs and metrics permissions if both are enabled 1`] = ` +exports[`getMonitoringPermissions With elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` Object { "_elastic_agent_monitoring": Object { "indices": Array [ @@ -15,16 +15,25 @@ Object { }, Object { "names": Array [ - "metrics-elastic_agent.metricbeat-testnamespace123", + "logs-elastic_agent.filebeat-testnamespace123", ], "privileges": Array [ "auto_configure", "create_doc", ], }, + ], + }, +} +`; + +exports[`getMonitoringPermissions With elastic agent package installed should return default logs, metrics, traces permissions if all are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ Object { "names": Array [ - "logs-elastic_agent.filebeat-testnamespace123", + "logs-elastic_agent.metricbeat-testnamespace123", ], "privileges": Array [ "auto_configure", @@ -33,25 +42,16 @@ Object { }, Object { "names": Array [ - "metrics-elastic_agent.filebeat-testnamespace123", + "metrics-elastic_agent.metricbeat-testnamespace123", ], "privileges": Array [ "auto_configure", "create_doc", ], }, - ], - }, -} -`; - -exports[`getMonitoringPermissions With elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` -Object { - "_elastic_agent_monitoring": Object { - "indices": Array [ Object { "names": Array [ - "logs-elastic_agent.metricbeat-testnamespace123", + "logs-elastic_agent.filebeat-testnamespace123", ], "privileges": Array [ "auto_configure", @@ -60,7 +60,7 @@ Object { }, Object { "names": Array [ - "logs-elastic_agent.filebeat-testnamespace123", + "metrics-elastic_agent.filebeat-testnamespace123", ], "privileges": Array [ "auto_configure", @@ -99,7 +99,15 @@ Object { } `; -exports[`getMonitoringPermissions Without elastic agent package installed should return default logs and metrics permissions if both are enabled 1`] = ` +exports[`getMonitoringPermissions With elastic agent package installed should return default traces permissions if only traces are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [], + }, +} +`; + +exports[`getMonitoringPermissions Without elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` Object { "_elastic_agent_monitoring": Object { "indices": Array [ @@ -122,23 +130,6 @@ Object { "logs-elastic_agent.pf_host_agent-testnamespace123", "logs-elastic_agent.pf_elastic_collector-testnamespace123", "logs-elastic_agent.pf_elastic_symbolizer-testnamespace123", - "metrics-elastic_agent-testnamespace123", - "metrics-elastic_agent.elastic_agent-testnamespace123", - "metrics-elastic_agent.apm_server-testnamespace123", - "metrics-elastic_agent.filebeat-testnamespace123", - "metrics-elastic_agent.filebeat_input-testnamespace123", - "metrics-elastic_agent.fleet_server-testnamespace123", - "metrics-elastic_agent.metricbeat-testnamespace123", - "metrics-elastic_agent.osquerybeat-testnamespace123", - "metrics-elastic_agent.packetbeat-testnamespace123", - "metrics-elastic_agent.endpoint_security-testnamespace123", - "metrics-elastic_agent.auditbeat-testnamespace123", - "metrics-elastic_agent.heartbeat-testnamespace123", - "metrics-elastic_agent.cloudbeat-testnamespace123", - "metrics-elastic_agent.cloud_defend-testnamespace123", - "metrics-elastic_agent.pf_host_agent-testnamespace123", - "metrics-elastic_agent.pf_elastic_collector-testnamespace123", - "metrics-elastic_agent.pf_elastic_symbolizer-testnamespace123", ], "privileges": Array [ "auto_configure", @@ -150,7 +141,7 @@ Object { } `; -exports[`getMonitoringPermissions Without elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` +exports[`getMonitoringPermissions Without elastic agent package installed should return default logs, metrics, traces permissions if all are enabled 1`] = ` Object { "_elastic_agent_monitoring": Object { "indices": Array [ @@ -173,6 +164,40 @@ Object { "logs-elastic_agent.pf_host_agent-testnamespace123", "logs-elastic_agent.pf_elastic_collector-testnamespace123", "logs-elastic_agent.pf_elastic_symbolizer-testnamespace123", + "metrics-elastic_agent-testnamespace123", + "metrics-elastic_agent.elastic_agent-testnamespace123", + "metrics-elastic_agent.apm_server-testnamespace123", + "metrics-elastic_agent.filebeat-testnamespace123", + "metrics-elastic_agent.filebeat_input-testnamespace123", + "metrics-elastic_agent.fleet_server-testnamespace123", + "metrics-elastic_agent.metricbeat-testnamespace123", + "metrics-elastic_agent.osquerybeat-testnamespace123", + "metrics-elastic_agent.packetbeat-testnamespace123", + "metrics-elastic_agent.endpoint_security-testnamespace123", + "metrics-elastic_agent.auditbeat-testnamespace123", + "metrics-elastic_agent.heartbeat-testnamespace123", + "metrics-elastic_agent.cloudbeat-testnamespace123", + "metrics-elastic_agent.cloud_defend-testnamespace123", + "metrics-elastic_agent.pf_host_agent-testnamespace123", + "metrics-elastic_agent.pf_elastic_collector-testnamespace123", + "metrics-elastic_agent.pf_elastic_symbolizer-testnamespace123", + "traces-elastic_agent-testnamespace123", + "traces-elastic_agent.elastic_agent-testnamespace123", + "traces-elastic_agent.apm_server-testnamespace123", + "traces-elastic_agent.filebeat-testnamespace123", + "traces-elastic_agent.filebeat_input-testnamespace123", + "traces-elastic_agent.fleet_server-testnamespace123", + "traces-elastic_agent.metricbeat-testnamespace123", + "traces-elastic_agent.osquerybeat-testnamespace123", + "traces-elastic_agent.packetbeat-testnamespace123", + "traces-elastic_agent.endpoint_security-testnamespace123", + "traces-elastic_agent.auditbeat-testnamespace123", + "traces-elastic_agent.heartbeat-testnamespace123", + "traces-elastic_agent.cloudbeat-testnamespace123", + "traces-elastic_agent.cloud_defend-testnamespace123", + "traces-elastic_agent.pf_host_agent-testnamespace123", + "traces-elastic_agent.pf_elastic_collector-testnamespace123", + "traces-elastic_agent.pf_elastic_symbolizer-testnamespace123", ], "privileges": Array [ "auto_configure", @@ -217,3 +242,37 @@ Object { }, } `; + +exports[`getMonitoringPermissions Without elastic agent package installed should return default traces permissions if only traces are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "traces-elastic_agent-testnamespace123", + "traces-elastic_agent.elastic_agent-testnamespace123", + "traces-elastic_agent.apm_server-testnamespace123", + "traces-elastic_agent.filebeat-testnamespace123", + "traces-elastic_agent.filebeat_input-testnamespace123", + "traces-elastic_agent.fleet_server-testnamespace123", + "traces-elastic_agent.metricbeat-testnamespace123", + "traces-elastic_agent.osquerybeat-testnamespace123", + "traces-elastic_agent.packetbeat-testnamespace123", + "traces-elastic_agent.endpoint_security-testnamespace123", + "traces-elastic_agent.auditbeat-testnamespace123", + "traces-elastic_agent.heartbeat-testnamespace123", + "traces-elastic_agent.cloudbeat-testnamespace123", + "traces-elastic_agent.cloud_defend-testnamespace123", + "traces-elastic_agent.pf_host_agent-testnamespace123", + "traces-elastic_agent.pf_elastic_collector-testnamespace123", + "traces-elastic_agent.pf_elastic_symbolizer-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts index 6a084b5dde586..d2ff49b04e340 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts @@ -221,6 +221,7 @@ describe('getFullAgentPolicy', () => { enabled: false, logs: false, metrics: false, + traces: false, }, }, }); @@ -257,6 +258,7 @@ describe('getFullAgentPolicy', () => { enabled: true, logs: true, metrics: false, + traces: false, }, }, }); @@ -293,12 +295,50 @@ describe('getFullAgentPolicy', () => { enabled: true, logs: false, metrics: true, + traces: false, }, }, }); }); - it('should return a policy with monitoring enabled but no logs/metrics if keep_monitoring_alive is true', async () => { + it('should return a policy with monitoring if monitoring is enabled for traces', async () => { + mockAgentPolicy({ + namespace: 'default', + revision: 1, + monitoring_enabled: ['traces'], + }); + const agentPolicy = await getFullAgentPolicy(savedObjectsClientMock.create(), 'agent-policy'); + + expect(agentPolicy).toMatchObject({ + id: 'agent-policy', + outputs: { + default: { + type: 'elasticsearch', + hosts: ['http://127.0.0.1:9201'], + }, + }, + inputs: [], + revision: 1, + fleet: { + hosts: ['http://fleetserver:8220'], + }, + agent: { + download: { + sourceURI: 'http://default-registry.co', + }, + monitoring: { + namespace: 'default', + use_output: 'default', + enabled: true, + logs: false, + metrics: false, + traces: true, + }, + }, + }); + }); + + it('should return a policy with monitoring enabled but no logs/metrics/traces if keep_monitoring_alive is true', async () => { mockAgentPolicy({ keep_monitoring_alive: true, }); @@ -309,6 +349,7 @@ describe('getFullAgentPolicy', () => { enabled: true, logs: false, metrics: false, + traces: false, }); }); @@ -325,6 +366,7 @@ describe('getFullAgentPolicy', () => { { logs: false, metrics: true, + traces: false, }, 'testnamespace' ); @@ -553,6 +595,7 @@ describe('getFullAgentPolicy', () => { enabled: true, logs: false, metrics: true, + traces: false, }, }, }); @@ -590,6 +633,7 @@ describe('getFullAgentPolicy', () => { enabled: true, logs: false, metrics: true, + traces: false, }, features: { fqdn: { @@ -743,6 +787,7 @@ describe('getFullAgentPolicy', () => { enabled: false, logs: false, metrics: false, + traces: false, }, }, fleet: { diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index a65b4ce8dc9fd..d00721f08a3d9 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -140,12 +140,13 @@ export async function getFullAgentPolicy( enabled: false, logs: false, metrics: false, + traces: false, }; let monitoring: FullAgentPolicyMonitoring = { ...defaultMonitoringConfig }; - // If the agent policy has monitoring enabled for at least one of "logs" or "metrics", generate - // a monitoring config for the resulting compiled agent policy + // If the agent policy has monitoring enabled for at least one of "logs", "metrics", or "traces" + // generate a monitoring config for the resulting compiled agent policy if (agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0) { monitoring = { namespace: agentPolicy.namespace, @@ -153,6 +154,7 @@ export async function getFullAgentPolicy( enabled: true, logs: agentPolicy.monitoring_enabled.includes(dataTypes.Logs), metrics: agentPolicy.monitoring_enabled.includes(dataTypes.Metrics), + traces: agentPolicy.monitoring_enabled.includes(dataTypes.Traces), }; // If the `keep_monitoring_alive` flag is set, enable monitoring but don't enable logs or metrics. // This allows cloud or other environments to keep the monitoring server alive without tearing it down. @@ -161,6 +163,7 @@ export async function getFullAgentPolicy( enabled: true, logs: false, metrics: false, + traces: false, }; } @@ -249,6 +252,7 @@ export async function getFullAgentPolicy( { logs: agentPolicy.monitoring_enabled?.includes(dataTypes.Logs) ?? false, metrics: agentPolicy.monitoring_enabled?.includes(dataTypes.Metrics) ?? false, + traces: agentPolicy.monitoring_enabled?.includes(dataTypes.Traces) ?? false, }, agentPolicy.namespace ); diff --git a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts index f336fd093c3af..0f72997cc3f2c 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts @@ -19,10 +19,10 @@ const mockedGetPackageInfo = getPackageInfo as jest.Mock { describe('Without elastic agent package installed', () => { - it('should return default logs and metrics permissions if both are enabled', async () => { + it('should return default logs, metrics, traces permissions if all are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: true, metrics: true }, + { logs: true, metrics: true, traces: true }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); @@ -30,7 +30,7 @@ describe('getMonitoringPermissions', () => { it('should return default logs permissions if only logs are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: true, metrics: false }, + { logs: true, metrics: false, traces: false }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); @@ -38,16 +38,24 @@ describe('getMonitoringPermissions', () => { it('should return default metrics permissions if only metrics are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: false, metrics: true }, + { logs: false, metrics: true, traces: false }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default traces permissions if only traces are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: false, metrics: false, traces: true }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); }); - it('should an empty valid permission entry if neither metrics and logs are enabled', async () => { + it('should an empty valid permission entry if neither metrics, logs, nor traces are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: false, metrics: false }, + { logs: false, metrics: false, traces: false }, 'testnamespace123' ); expect(permissions).toEqual({ _elastic_agent_monitoring: { indices: [] } }); @@ -82,10 +90,10 @@ describe('getMonitoringPermissions', () => { ], } as PackageInfo); }); - it('should return default logs and metrics permissions if both are enabled', async () => { + it('should return default logs, metrics, traces permissions if all are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: true, metrics: true }, + { logs: true, metrics: true, traces: true }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); @@ -93,7 +101,7 @@ describe('getMonitoringPermissions', () => { it('should return default logs permissions if only logs are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: true, metrics: false }, + { logs: true, metrics: false, traces: false }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); @@ -101,7 +109,15 @@ describe('getMonitoringPermissions', () => { it('should return default metrics permissions if only metrics are enabled', async () => { const permissions = await getMonitoringPermissions( savedObjectsClientMock.create(), - { logs: false, metrics: true }, + { logs: false, metrics: true, traces: false }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default traces permissions if only traces are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: false, metrics: false, traces: true }, 'testnamespace123' ); expect(permissions).toMatchSnapshot(); diff --git a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts index 0729367c2b65b..e03a8e19eb120 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts @@ -18,7 +18,10 @@ import { dataTypes } from '../../../common/constants'; import { getDataStreamPrivileges } from './package_policies_to_agent_permissions'; -function buildDefault(enabled: { logs: boolean; metrics: boolean }, namespace: string) { +function buildDefault( + enabled: { logs: boolean; metrics: boolean; traces: boolean }, + namespace: string +) { let names: string[] = []; if (enabled.logs) { names = names.concat( @@ -30,6 +33,11 @@ function buildDefault(enabled: { logs: boolean; metrics: boolean }, namespace: s AGENT_POLICY_DEFAULT_MONITORING_DATASETS.map((dataset) => `metrics-${dataset}-${namespace}`) ); } + if (enabled.traces) { + names = names.concat( + AGENT_POLICY_DEFAULT_MONITORING_DATASETS.map((dataset) => `traces-${dataset}-${namespace}`) + ); + } if (names.length === 0) { return { @@ -53,7 +61,7 @@ function buildDefault(enabled: { logs: boolean; metrics: boolean }, namespace: s export async function getMonitoringPermissions( soClient: SavedObjectsClientContract, - enabled: { logs: boolean; metrics: boolean }, + enabled: { logs: boolean; metrics: boolean; traces: boolean }, namespace: string ): Promise { const installation = await getInstallation({ @@ -85,6 +93,9 @@ export async function getMonitoringPermissions( if (ds.type === dataTypes.Metrics && !enabled.metrics) { return; } + if (ds.type === dataTypes.Traces && !enabled.traces) { + return; + } return getDataStreamPrivileges(ds, namespace); }) .filter( From cbc8f173889ae1f377eadddabb3380179b74110a Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Mon, 26 Aug 2024 14:21:15 -0700 Subject: [PATCH 10/38] [Detection Engine] Update toast message for adding exception (#191032) ## Summary Addresses https://github.com/elastic/kibana/issues/156246 Updates exception toast message to accurately reflect when it's an endpoint exception. --- .../add_exception_flyout/helpers.test.ts | 21 ++++++++++++++++++- .../add_exception_flyout/helpers.ts | 12 +++++++++++ .../add_exception_flyout/translations.ts | 20 +++++++++++------- .../use_add_new_exceptions.ts | 7 +++++-- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 7 files changed, 49 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.test.ts index d8a1823622bdf..6937026e8ba0a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.test.ts @@ -10,7 +10,12 @@ import { getExceptionListSchemaMock } from '@kbn/lists-plugin/common/schemas/res import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { getRulesSchemaMock } from '../../../../../common/api/detection_engine/model/rule_schema/rule_response_schema.mock'; -import { isSubmitDisabled, prepareNewItemsForSubmission, prepareToCloseAlerts } from './helpers'; +import { + isSubmitDisabled, + prepareNewItemsForSubmission, + prepareToCloseAlerts, + getSuccessToastTitle, +} from './helpers'; import type { Rule } from '../../../rule_management/logic/types'; import type { AlertData } from '../../utils/types'; @@ -469,4 +474,18 @@ describe('add_exception_flyout#helpers', () => { expect(ruleStaticIds).toEqual(['query-rule-id']); }); }); + + describe('getSuccessToastTitle', () => { + it('returns endpoint title when list type is "endpoint"', () => { + expect(getSuccessToastTitle(ExceptionListTypeEnum.ENDPOINT)).toEqual( + 'Endpoint exception added to shared exception list' + ); + }); + + it('returns non endpoint title when list type is not "endpoint"', () => { + expect(getSuccessToastTitle(ExceptionListTypeEnum.DETECTION)).toEqual( + 'Rule exception added to shared exception list' + ); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.ts index 23d20f699780d..76478ddc67023 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/helpers.ts @@ -14,6 +14,7 @@ import type { ExceptionsBuilderReturnExceptionItem } from '@kbn/securitysolution import type { Rule } from '../../../rule_management/logic/types'; import { enrichNewExceptionItems } from '../flyout_components/utils'; import type { AlertData } from '../../utils/types'; +import * as i18n from './translations'; const RULE_DEFAULT_OPTIONS = ['add_to_rule', 'add_to_rules', 'select_rules_to_add_to']; @@ -183,3 +184,14 @@ export const prepareToCloseAlerts = ({ ruleStaticIds, }; }; + +export const getSuccessToastTitle = (listType: ExceptionListTypeEnum) => + listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.ADD_ENDPOINT_EXCEPTION_SUCCESS + : i18n.ADD_EXCEPTION_SUCCESS; + +export const getSuccessToastText = (listType: ExceptionListTypeEnum, sharedListNames: string[]) => + i18n.ADD_EXCEPTION_SUCCESS_DETAILS( + listType === ExceptionListTypeEnum.ENDPOINT ? 'Endpoint' : 'Rule', + sharedListNames.join(',') + ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts index d27d7994bb375..a8dbde51b2b56 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts @@ -53,14 +53,18 @@ export const ADD_EXCEPTION_SUCCESS = i18n.translate( } ); -export const ADD_EXCEPTION_SUCCESS_DETAILS = (listNames: string) => - i18n.translate( - 'xpack.securitySolution.ruleExceptions.addExceptionFlyout.closeAlerts.successDetails', - { - values: { listNames }, - defaultMessage: 'Rule exception has been added to shared lists: {listNames}.', - } - ); +export const ADD_ENDPOINT_EXCEPTION_SUCCESS = i18n.translate( + 'xpack.securitySolution.ruleExceptions.addEndpointException.success', + { + defaultMessage: 'Endpoint exception added to shared exception list', + } +); + +export const ADD_EXCEPTION_SUCCESS_DETAILS = (listType: string, listNames: string) => + i18n.translate('xpack.securitySolution.ruleExceptions.addExceptionFlyout.successDetails', { + values: { listNames, listType }, + defaultMessage: '{listType} exception has been added to shared lists: {listNames}.', + }); export const ADD_RULE_EXCEPTION_SUCCESS_TITLE = i18n.translate( 'xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessTitle', diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/use_add_new_exceptions.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/use_add_new_exceptions.ts index 7aa686ed43cdf..136a93ab13329 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/use_add_new_exceptions.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/use_add_new_exceptions.ts @@ -25,6 +25,7 @@ import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import type { Rule } from '../../../rule_management/logic/types'; import { useCreateOrUpdateException } from '../../logic/use_create_update_exception'; import { useAddRuleDefaultException } from '../../logic/use_add_rule_exception'; +import { getSuccessToastText, getSuccessToastTitle } from './helpers'; export interface AddNewExceptionItemHookProps { itemsToAdd: ExceptionsBuilderReturnExceptionItem[]; @@ -110,10 +111,12 @@ export const useAddNewExceptionItems = (): ReturnUseAddNewExceptionItems => { result = await addSharedExceptions(itemsToAdd); const sharedListNames = sharedLists.map(({ name }) => name); + const title = getSuccessToastTitle(listType); + const text = getSuccessToastText(listType, sharedListNames); addSuccess({ - title: i18n.ADD_EXCEPTION_SUCCESS, - text: i18n.ADD_EXCEPTION_SUCCESS_DETAILS(sharedListNames.join(',')), + title, + text, }); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 9d86049531ed7..3b5a402334797 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -40635,7 +40635,6 @@ "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionFromAlertComment": "Les conditions d'exceptions sont préremplies avec les données pertinentes d'une alerte possédant l'identifiant d'alerte (_id) : {alertId}.", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessText": "L'exception a été ajoutée aux règles - {ruleName}.", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessTitle": "Exception à la règle ajoutée", - "xpack.securitySolution.ruleExceptions.addExceptionFlyout.closeAlerts.successDetails": "L'exception de la règle a été ajoutée aux listes partagées : {listNames}.", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.commentsTitle": "Ajouter des commentaires ({comments})", "xpack.securitySolution.ruleExceptions.allExceptionItems.activeDetectionsLabel": "Exceptions actives", "xpack.securitySolution.ruleExceptions.allExceptionItems.addExceptionsEmptyPromptTitle": "Ajouter des exceptions à cette règle", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 260c61347241d..f88fabd25833d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -40618,7 +40618,6 @@ "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionFromAlertComment": "例外条件は、アラートID(_id)のアラートからの関連データがあらかじめ入力されます:{alertId}。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessText": "例外がルール - {ruleName}に追加されました。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessTitle": "ルール例外が追加されました", - "xpack.securitySolution.ruleExceptions.addExceptionFlyout.closeAlerts.successDetails": "ルール例外が共有リストに追加されました:{listNames}。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.commentsTitle": "コメントの追加({comments})", "xpack.securitySolution.ruleExceptions.allExceptionItems.activeDetectionsLabel": "アクティブな例外", "xpack.securitySolution.ruleExceptions.allExceptionItems.addExceptionsEmptyPromptTitle": "このルールに例外を追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 690519b75013f..2ae9e055b1f01 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -40661,7 +40661,6 @@ "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionFromAlertComment": "将使用具有告警 ID (_id) 的告警中的相关数据预填充例外条件:{alertId}。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessText": "例外已添加到规则 - {ruleName}。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.addRuleExceptionToastSuccessTitle": "已添加规则例外", - "xpack.securitySolution.ruleExceptions.addExceptionFlyout.closeAlerts.successDetails": "规则例外已添加到共享列表:{listNames}。", "xpack.securitySolution.ruleExceptions.addExceptionFlyout.commentsTitle": "添加注释 ({comments})", "xpack.securitySolution.ruleExceptions.allExceptionItems.activeDetectionsLabel": "活动例外", "xpack.securitySolution.ruleExceptions.allExceptionItems.addExceptionsEmptyPromptTitle": "将例外添加到此规则", From 4d5b1fa297f1573941e896345c0cdba6f7a80272 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Mon, 26 Aug 2024 14:22:09 -0700 Subject: [PATCH 11/38] [Detection Engine] update assignee popover text (#191035) ## Summary Addresses https://github.com/elastic/kibana/issues/173260 --- .../public/common/components/assignees/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/common/components/assignees/translations.ts b/x-pack/plugins/security_solution/public/common/components/assignees/translations.ts index fdd22f50aa7cb..a6073395f45fc 100644 --- a/x-pack/plugins/security_solution/public/common/components/assignees/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/assignees/translations.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; export const ASSIGNEES_SELECTION_STATUS_MESSAGE = (total: number) => i18n.translate('xpack.securitySolution.assignees.totalUsersAssigned', { - defaultMessage: '{total, plural, one {# filter} other {# filters}} selected', + defaultMessage: '{total, plural, one {# assignee} other {# assignees}} selected', values: { total }, }); From d07ffe2a04eb6fc935762158252b3aa8a0083335 Mon Sep 17 00:00:00 2001 From: Brad White Date: Mon, 26 Aug 2024 15:38:45 -0600 Subject: [PATCH 12/38] Add Kibana Dev Container (#188887) ## Summary - Closes elastic/kibana-operations#101 This PR adds a [Dev Container](https://containers.dev/) to utilize for Kibana local development in an isolated environment. The original intention was to create a local environment for FIPS development because setting up Kibana in FIPS mode is complicated and has the potential to break the user's OS. However, it has been altered to allow for general development if an engineer chooses as well. The idea is for this be a cost efficient replacement for [kibana-remote-dev](https://github.com/elastic/kibana-remote-dev) eventually. ### Testing - In VS Code you should be able to use the `Dev Containers: Clone GitHub Pull Request in Named Container Volume...` command from the Command Palette (F1) to easily test this PR. - See the [docs](https://github.com/elastic/kibana/blob/bd125fc230f06848d62a564dc88d8abfb4f13e88/dev_docs/getting_started/setting_up_a_development_env.mdx#using-the-kibana-dev-container-optional) for additional information on setting up the Dev Container. ### Bazel I tried many different solutions to copy the local Bazel cache into the container to speed up bootstrap, but it either would break Bazel or didn't provide any meaningful boost in performance. I opted to forgo keeping it in this PR due to the complexity and since we're planning to phase out Bazel in the future anyways. --- .devcontainer/.env.template | 4 ++ .devcontainer/Dockerfile | 69 +++++++++++++++++++ .devcontainer/README.md | 1 + .devcontainer/config/nodejs.cnf | 28 ++++++++ .devcontainer/devcontainer.json | 41 +++++++++++ .devcontainer/scripts/env.sh | 48 +++++++++++++ .devcontainer/scripts/post_start.sh | 8 +++ .github/CODEOWNERS | 1 + .gitignore | 5 +- .../setting_up_a_development_env.mdx | 29 +++++++- renovate.json | 10 ++- 11 files changed, 240 insertions(+), 4 deletions(-) create mode 100644 .devcontainer/.env.template create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/README.md create mode 100644 .devcontainer/config/nodejs.cnf create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/scripts/env.sh create mode 100755 .devcontainer/scripts/post_start.sh diff --git a/.devcontainer/.env.template b/.devcontainer/.env.template new file mode 100644 index 0000000000000..3ca02c49bfa9c --- /dev/null +++ b/.devcontainer/.env.template @@ -0,0 +1,4 @@ +# /bin/bash or /bin/zsh (oh-my-zsh is installed by default as well) +SHELL=/bin/bash +# Switch to 1 to enable FIPS environment, any other value to disable +FIPS=0 diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000000..539e23a4a3a31 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,69 @@ +FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04 + +ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 +ENV HOME=/home/vscode +ENV NVM_DIR=${HOME}/nvm +ENV NVM_VERSION=v0.39.1 +ENV KBN_DIR=/workspaces/kibana +ENV OPENSSL_PATH=${HOME}/openssl +# Only specific versions are FIPS certified. +ENV OPENSSL_VERSION='3.0.8' + +RUN apt-get update && apt-get install -y curl git zsh locales docker.io perl make gcc xvfb + +RUN locale-gen en_US.UTF-8 + +# Oh My Zsh setup +RUN if [ ! -d "$HOME/.oh-my-zsh" ]; then \ + sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"; \ + fi && \ + ZSH_CUSTOM=${ZSH_CUSTOM:-~/.oh-my-zsh/custom} && \ + if [ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]; then \ + git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions; \ + fi && \ + sed -i 's/plugins=(git)/plugins=(git ssh-agent npm docker zsh-autosuggestions)/' /home/vscode/.zshrc + +# Docker-in-Docker setup +RUN usermod -aG docker vscode + +# FIPS setup +# https://github.com/openssl/openssl/blob/openssl-3.0/README-FIPS.md +# https://www.openssl.org/docs/man3.0/man7/fips_module.html +WORKDIR ${HOME} + +RUN set -e ; \ + mkdir -p "${OPENSSL_PATH}"; \ + curl --retry 8 -S -L -O "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" ; \ + curl --retry 8 -S -L -O "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz.sha256" ; \ + echo "$(cat openssl-${OPENSSL_VERSION}.tar.gz.sha256) openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c ; \ + tar -zxf "openssl-${OPENSSL_VERSION}.tar.gz" ; \ + rm -rf openssl-${OPENSSL_VERSION}.tar* ; \ + cd "${OPENSSL_PATH}-${OPENSSL_VERSION}" ; \ + ./Configure --prefix="${OPENSSL_PATH}" --openssldir="${OPENSSL_PATH}/ssl" --libdir="${OPENSSL_PATH}/lib" shared -Wl,-rpath,${OPENSSL_PATH}/lib enable-fips; \ + make -j $(nproc) > /dev/null ; \ + make install > /dev/null ; \ + rm -rf "${OPENSSL_PATH}-${OPENSSL_VERSION}" ; \ + chown -R 1000:1000 "${OPENSSL_PATH}"; + +WORKDIR ${KBN_DIR} + +# Node and NVM setup +COPY .node-version /tmp/ +RUN mkdir -p $NVM_DIR && \ + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash && \ + . "$NVM_DIR/nvm.sh" && \ + NODE_VERSION=$(cat /tmp/.node-version) && \ + nvm install ${NODE_VERSION} && \ + nvm use ${NODE_VERSION} && \ + nvm alias default ${NODE_VERSION} && \ + npm install -g yarn && \ + echo "source $NVM_DIR/nvm.sh" >> ${HOME}/.bashrc && \ + echo "source $NVM_DIR/nvm.sh" >> ${HOME}/.zshrc && \ + chown -R 1000:1000 "${HOME}/.npm" + +# Reload the env everytime a new shell is opened incase the .env file changed. +RUN echo "source $KBN_DIR/.devcontainer/scripts/env.sh" >> ${HOME}/.bashrc && \ + echo "source $KBN_DIR/.devcontainer/scripts/env.sh" >> ${HOME}/.zshrc + +# This is for documentation. Ports are exposed via devcontainer.json +EXPOSE 9200 5601 9229 9230 9231 diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000000000..835ce0f756499 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1 @@ +See the [dev docs](https://github.com/elastic/kibana/blob/main/dev_docs/getting_started/setting_up_a_development_env.mdx#using-the-kibana-dev-container-optional) for information on using the Kibana Dev Container. \ No newline at end of file diff --git a/.devcontainer/config/nodejs.cnf b/.devcontainer/config/nodejs.cnf new file mode 100644 index 0000000000000..eef11d640e198 --- /dev/null +++ b/.devcontainer/config/nodejs.cnf @@ -0,0 +1,28 @@ +########################################################################## +## ## +## This OpenSSL config is only loaded when running Kibana in FIPS mode. ## +## ## +## See: ## +## https://github.com/openssl/openssl/blob/openssl-3.0/README-FIPS.md ## +## https://www.openssl.org/docs/man3.0/man7/fips_module.html ## +## ## +########################################################################## + +nodejs_conf = nodejs_init +.include /home/vscode/openssl/ssl/fipsmodule.cnf + +[nodejs_init] +providers = provider_sect +alg_section = algorithm_sect + +[provider_sect] +default = default_sect +# The fips section name should match the section name inside the +# included fipsmodule.cnf. +fips = fips_sect + +[default_sect] +activate = 1 + +[algorithm_sect] +default_properties = fips=yes \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000000..f5fea9e37c5d3 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,41 @@ +{ + "name": "Kibana", + "build": { + "dockerfile": "Dockerfile", + "context": ".." + }, + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "ms-azuretools.vscode-docker", + "editorconfig.editorconfig", + "timonwong.shellcheck", + "eamodio.gitlens", + "github.vscode-pull-request-github" + ] + } + }, + "forwardPorts": [ + 9200, + 5601, + 9229, + 9230, + 9231 + ], + "postStartCommand": "/workspaces/kibana/.devcontainer/scripts/post_start.sh", + "remoteUser": "vscode", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "dockerDashComposeVersion": "latest" + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + }, + "ghcr.io/kreemer/features/chrometesting:1": { + "version": "stable" + } + } +} diff --git a/.devcontainer/scripts/env.sh b/.devcontainer/scripts/env.sh new file mode 100755 index 0000000000000..77c2000663e5f --- /dev/null +++ b/.devcontainer/scripts/env.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +ENV_PATH="${KBN_DIR}/.devcontainer/.env" +KBN_CONFIG_FILE="${KBN_DIR}/config/kibana.dev.yml" + +setup_fips() { + if [ ! -f "$KBN_CONFIG_FILE" ]; then + touch "$KBN_CONFIG_FILE" + fi + + if [ -n "$FIPS" ] && [ "$FIPS" = "1" ]; then + sed -i '/xpack.security.experimental.fipsMode.enabled:/ {s/.*/xpack.security.experimental.fipsMode.enabled: true/; t}; $a\xpack.security.experimental.fipsMode.enabled: true' "$KBN_CONFIG_FILE" + + # Patch node_modules so we can start Kibana in dev mode + sed -i 's/hashType = hashType || '\''md5'\'';/hashType = hashType || '\''sha1'\'';/g' "${KBN_DIR}/node_modules/file-loader/node_modules/loader-utils/lib/getHashDigest.js" + sed -i 's/const hash = createHash("md4");/const hash = createHash("sha1");/g' "${KBN_DIR}/node_modules/webpack/lib/ModuleFilenameHelpers.js" + sed -i 's/contentHash: createHash("md4")/contentHash: createHash("sha1")/g' "${KBN_DIR}/node_modules/webpack/lib/SourceMapDevToolPlugin.js" + + export OPENSSL_MODULES="$OPENSSL_PATH/lib/ossl-modules" + export NODE_OPTIONS="--enable-fips --openssl-config=$KBN_DIR/.devcontainer/config/nodejs.cnf" + echo "FIPS mode enabled" + echo "If manually bootstrapping in FIPS mode use: NODE_OPTIONS='' yarn kbn bootstrap" + else + sed -i '/xpack.security.experimental.fipsMode.enabled:/ {s/.*/xpack.security.experimental.fipsMode.enabled: false/; t}; $a\xpack.security.experimental.fipsMode.enabled: false' "$KBN_CONFIG_FILE" + fi +} + +setup_shell() { + if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then + current_shell=$(ps -p $$ -o comm=) + desired_shell=$(basename "$SHELL") + + if [ "$current_shell" != "$desired_shell" ]; then + sudo chsh -s "$SHELL" vscode + exec "$SHELL" + fi + else + echo "Shell is not set or not executable, using bash" + fi +} + +if [ -f "$ENV_PATH" ]; then + source "$ENV_PATH" + setup_fips + setup_shell +else + echo ".env file not found, using default values" +fi diff --git a/.devcontainer/scripts/post_start.sh b/.devcontainer/scripts/post_start.sh new file mode 100755 index 0000000000000..78490bb73d513 --- /dev/null +++ b/.devcontainer/scripts/post_start.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# If FIPS mode is enabled, there can be issues installing some dependencies due to invalid algorithms. +# So override the NODE_OPTIONS environment variable to disable FIPS mode. +NODE_OPTIONS='' yarn kbn bootstrap + +Xvfb :99 -screen 0 1920x1080x24 & +export DISPLAY=:99 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 277ac73bedf0c..450fbb023af95 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1279,6 +1279,7 @@ x-pack/test/observability_ai_assistant_functional @elastic/obs-ai-assistant /kbn_pm/ @elastic/kibana-operations /x-pack/dev-tools @elastic/kibana-operations /catalog-info.yaml @elastic/kibana-operations @elastic/kibana-tech-leads +/.devcontainer/ @elastic/kibana-operations # Appex QA /src/dev/code_coverage @elastic/appex-qa diff --git a/.gitignore b/.gitignore index 1936413e13609..02f11f9275184 100644 --- a/.gitignore +++ b/.gitignore @@ -142,10 +142,13 @@ x-pack/test/security_api_integration/plugins/audit_log/audit.log .ftr role_users.json + +.devcontainer/.env + # Ignore temporary files in oas_docs output/kibana.serverless.tmp1.yaml output/kibana.serverless.tmp2.yaml output/kibana.tmp1.yaml output/kibana.tmp2.yaml output/kibana.new.yaml -output/kibana.serverless.new.yaml \ No newline at end of file +output/kibana.serverless.new.yaml diff --git a/dev_docs/getting_started/setting_up_a_development_env.mdx b/dev_docs/getting_started/setting_up_a_development_env.mdx index 49b745f9d0f0d..a63dfdce59b4d 100644 --- a/dev_docs/getting_started/setting_up_a_development_env.mdx +++ b/dev_docs/getting_started/setting_up_a_development_env.mdx @@ -3,8 +3,8 @@ id: kibDevTutorialSetupDevEnv slug: /kibana-dev-docs/getting-started/setup-dev-env title: Set up a Development Environment description: Learn how to setup a development environment for contributing to the Kibana repository -date: 2022-07-07 -tags: ['kibana', 'onboarding', 'dev', 'architecture', 'setup'] +date: 2024-08-09 +tags: ['kibana', 'onboarding', 'dev', 'architecture', 'setup', 'devcontainer'] --- Setting up a development environment is pretty easy. @@ -92,3 +92,28 @@ node scripts/register_git_hook ``` After the script completes the pre-commit hook will be created within the file `.git/hooks/pre-commit`. If you choose to not install it, don’t worry, we still run a quick CI check to provide feedback earliest as we can about the same checks. + +## Using the Kibana Dev Container (optional) + +Kibana also supports using a [dev container](https://containers.dev/) which can integrate with various editors and tools [(supported tools)](https://containers.dev/supporting). The dev container provides a consistent development environment across different machines and setups which is based on Ubuntu Jammy (22.04). The only prerequisite is having [Docker](https://www.docker.com/) installed locally. VS Code is the recommended editor and will be used for these instructions because it is the most mature, but it is not required. + +### Setting up the Dev Container + +1. Make a copy of `.devcontainer/.env.template` and rename it to `.devcontainer/.env`. Edit any values you're interested in. +1. There are three options for mounting the Kibana repo into the container: + - **Local Filesystem**: Clone the repo locally, or use an existing copy, and open it in VS Code. When prompted, select "Reopen in Dev Container". This uses a bind mount, allowing the container to access and modify files directly on your local filesystem. Your git credentials should be automatically mounted in the container as well. Note that Bazel will create symlinks and a cache inside the container file system. So, if switching to working on your local filesystem afterwards, you will need to bootstrap again. + - **Docker Repo Volume**: Use the `Dev Containers: Clone Repository in Named Container Volume...` command from the Command Palette (`F1`). This clones the repo into a Docker volume, isolating it from your local filesystem. You will need to configure your git credentials manually in this isolated environment. + - **Docker PR Volume**: Use the `Dev Containers: Clone GitHub Pull Request in Named Container Volume...` command from the Command Palette (`F1`). This is the same as the previous option, but can be useful for testing a PR in insolation of your local filesystem. +1. VS Code will then build the container, this will take a few minutes the first time, but subsequent builds will utilize Docker caching and be much faster. +1. Once the container is built and started, it will automatically run `yarn kbn bootstrap`. +1. You should see the Kibana repo and your terminal will be inside the container. You can develop as normal now, including running `yarn es` from inside the container. + +### Customizing the Dev Container +Installing any extra extensions or making adjustments to the OS environment inside the container will not have an effect on your local OS or VS Code installation. Editing the `devcontainer.json` or `.devcontainer/Dockerfile` should be reserved for changes to all dev environments. + +### FIPS Mode + +The dev container is pre-configured to run Kibana in FIPS mode if needed. Simply change the `.env` file to `FIPS=1` and reopen your terminal. There should be a log message in your terminal which indicates `FIPS mode enabled`. + +### Troubleshooting +- Sometimes when rebuilding the container, there will be an error message that it failed. Usually hitting retry will fix this, and is only related to VS Code trying to reconnect to the container too quickly. \ No newline at end of file diff --git a/renovate.json b/renovate.json index 31f8630a3ad87..774dce52e3515 100644 --- a/renovate.json +++ b/renovate.json @@ -2,7 +2,7 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver"], "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], - "enabledManagers": ["npm", "github-actions", "custom.regex"], + "enabledManagers": ["npm", "github-actions", "custom.regex", "devcontainer"], "baseBranches": ["main", "7.17"], "prConcurrentLimit": 0, "prHourlyLimit": 0, @@ -20,6 +20,14 @@ "matchDepPatterns": [".*"], "enabled": false }, + { + "groupName": "devcontainer", + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip", "backport:current-major"], + "enabled": true, + "matchManagers": ["devcontainer"] + }, { "groupName": "chainguard", "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], From 64f1ae6c4889180aa92616b2bb221a3c0728f645 Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Mon, 26 Aug 2024 15:02:03 -0700 Subject: [PATCH 13/38] [Unified Search][Lens] Focus selectable search inputs in dropdowns (#191213) ## Summary Adds `autoFocus` search input in dropdown for the global **Data view** selector and the **Lens chart switch**. Now clicking on either dropdown, the focus will automatically be on the input for the user to start typing to filter selectable items. This does not change the tab indexing of the surrounding elements. ### Data view picker ![Zight Recording 2024-08-23 at 09 11 47 AM](https://github.com/user-attachments/assets/c5cf9981-4e79-4216-b1ae-0ef5da8fe62a) ### Lens chart switch ![Zight Recording 2024-08-23 at 09 14 09 AM](https://github.com/user-attachments/assets/7fb117b5-0bb7-4204-a606-264ce12a1f6d) closes #189686 ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Elastic Machine Co-authored-by: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> --- .../unified_search/public/dataview_picker/dataview_list.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx b/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx index 003f8181bfefb..559174711af3b 100644 --- a/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx +++ b/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx @@ -149,6 +149,7 @@ export function DataViewsList({ searchProps={{ id: searchListInputId, compressed: true, + autoFocus: true, placeholder: strings.editorAndPopover.search.getSearchPlaceholder(), 'data-test-subj': 'indexPattern-switcher--input', ...(selectableProps ? selectableProps.searchProps : undefined), From 6538c09c6294eb8bc84aa0b3a3e62e6f38aa4ae8 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 26 Aug 2024 17:40:26 -0500 Subject: [PATCH 14/38] [ci] Add CodeQL pipeline (#191293) Only a placeholder for the moment https://github.com/elastic/kibana/issues/150521 --- .../kibana-codeql.yml | 34 +++++++++++++++++++ .../locations.yml | 1 + .buildkite/pipelines/codeql/codeql.yml | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 .buildkite/pipeline-resource-definitions/kibana-codeql.yml create mode 100644 .buildkite/pipelines/codeql/codeql.yml diff --git a/.buildkite/pipeline-resource-definitions/kibana-codeql.yml b/.buildkite/pipeline-resource-definitions/kibana-codeql.yml new file mode 100644 index 0000000000000..3da2c9137c4e0 --- /dev/null +++ b/.buildkite/pipeline-resource-definitions/kibana-codeql.yml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: bk-kibana-codeql + description: Run CodeQL + links: + - title: Pipeline link + url: https://buildkite.com/elastic/kibana-codeql +spec: + type: buildkite-pipeline + owner: group:kibana-operations + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: kibana / codeql + description: Run CodeQL + spec: + env: + SLACK_NOTIFICATIONS_CHANNEL: "#kibana-operations-alerts" + ELASTIC_SLACK_NOTIFICATIONS_ENABLED: "false" + repository: elastic/kibana + branch_configuration: main + default_branch: main + pipeline_file: ".buildkite/pipelines/codeql/codeql.yml" + provider_settings: + trigger_mode: none + teams: + kibana-operations: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: READ_ONLY diff --git a/.buildkite/pipeline-resource-definitions/locations.yml b/.buildkite/pipeline-resource-definitions/locations.yml index 45a155d21280e..5144982a0627d 100644 --- a/.buildkite/pipeline-resource-definitions/locations.yml +++ b/.buildkite/pipeline-resource-definitions/locations.yml @@ -44,3 +44,4 @@ spec: - https://github.com/elastic/kibana/blob/main/.buildkite/pipeline-resource-definitions/security-solution-quality-gate/kibana-serverless-security-solution-quality-gate-rule-management.yml - https://github.com/elastic/kibana/blob/main/.buildkite/pipeline-resource-definitions/trigger-version-dependent-jobs.yml - https://github.com/elastic/kibana/blob/main/.buildkite/pipeline-resource-definitions/kibana-pointer-compression.yml + - https://github.com/elastic/kibana/blob/main/.buildkite/pipeline-resource-definitions/kibana-codeql.yml diff --git a/.buildkite/pipelines/codeql/codeql.yml b/.buildkite/pipelines/codeql/codeql.yml new file mode 100644 index 0000000000000..52fc4f910713a --- /dev/null +++ b/.buildkite/pipelines/codeql/codeql.yml @@ -0,0 +1,2 @@ +steps: + - command: echo "Placeholder" From c361abd78c863c2e21a0cfd12adceaf4804cd3c9 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Mon, 26 Aug 2024 16:25:14 -0700 Subject: [PATCH 15/38] [UII] Use signed version of old endpoint package for setup test (#191311) ## Summary As the title says :) --- x-pack/test/fleet_api_integration/apis/epm/setup.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/fleet_api_integration/apis/epm/setup.ts b/x-pack/test/fleet_api_integration/apis/epm/setup.ts index ac43d7a141a25..001cab435d75b 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/setup.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/setup.ts @@ -32,9 +32,9 @@ export default function (providerContext: FtrProviderContext) { await uninstallPackage('deprecated', '0.1.0'); await uninstallPackage('multiple_versions', '0.3.0'); }); - // FLAKY: https://github.com/elastic/kibana/issues/118479 - describe.skip('setup performs upgrades', async () => { - const oldEndpointVersion = '0.13.0'; + + describe('setup performs upgrades', async () => { + const oldEndpointVersion = '1.0.0'; beforeEach(async () => { const url = '/api/fleet/epm/packages/endpoint'; await supertest.delete(url).set('kbn-xsrf', 'xxxx').send({ force: true }).expect(200); From d0319c6555367100ff054221b6d67b454c50ed2a Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:28:38 -0700 Subject: [PATCH 16/38] [Response Ops][Maintenance Window] Fix MW bug where rules that generate multiple alerts only has 1 alert that gets muted (#190935) ## Summary Issue: https://github.com/elastic/kibana/issues/190750 Fix a bug with maintenance window where only 1 alert from a rule that generates multiple alerts has the maintenance window ID associated. The fix was to remove a `size` field (not sure why that was there). To verify: 1. Create an active maintenance window with conditional filter 2. Create a rule that matches the maintenance window filter and let it generate multiple alerts (I use ES query rule on the task_manager index with runAt as timefield. Then use groupBy on the runAt field.). 3. Assert that all of the alerts generated have the maintenance window ID associated with it ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Elastic Machine --- .../lib/get_summarized_alerts_query.ts | 1 - .../plugins/alerts/server/rule_types.ts | 2 +- .../group3/maintenance_window_scoped_query.ts | 70 ++++++++++++++++++- .../tests/alerting/group3/test_helpers.ts | 2 +- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts b/x-pack/plugins/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts index e9e706331f360..4f0aa0fb003df 100644 --- a/x-pack/plugins/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts +++ b/x-pack/plugins/alerting/server/alerts_client/lib/get_summarized_alerts_query.ts @@ -324,7 +324,6 @@ export const getQueryByScopedQueries = ({ aggs: { alertId: { top_hits: { - size: 1, _source: { includes: [ALERT_UUID], }, diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/rule_types.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/rule_types.ts index 498020cb4b7d2..0700cba718324 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/rule_types.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/rule_types.ts @@ -917,7 +917,7 @@ function getAlwaysFiringAlertAsDataRuleType( validate: { params: paramsSchema, }, - category: 'kibana', + category: 'management', producer: 'alertsFixture', defaultActionGroupId: 'default', minimumLicenseRequired: 'basic', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_scoped_query.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_scoped_query.ts index b0900bc48c4bc..03880f79b5b14 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_scoped_query.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_scoped_query.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import type { Alert } from '@kbn/alerts-as-data-utils'; import { ALERT_MAINTENANCE_WINDOW_IDS } from '@kbn/rule-data-utils'; -import { ObjectRemover } from '../../../../common/lib'; +import { getTestRuleData, getUrlPrefix, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { createRule, @@ -18,6 +18,7 @@ import { expectNoActionsFired, runSoon, } from './test_helpers'; +import { Spaces } from '../../../scenarios'; const alertAsDataIndex = '.internal.alerts-test.patternfiring.alerts-default-000001'; @@ -177,5 +178,72 @@ export default function maintenanceWindowScopedQueryTests({ getService }: FtrPro getService, }); }); + + it('should associate alerts for rules that generate multiple alerts', async () => { + await createMaintenanceWindow({ + supertest, + objectRemover, + overwrites: { + scoped_query: { + kql: 'kibana.alert.rule.tags: "test"', + filters: [], + }, + category_ids: ['management'], + }, + }); + + // Create action and rule + const action = await await createAction({ + supertest, + objectRemover, + }); + + const { body: rule } = await supertestWithoutAuth + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + name: 'test-rule', + rule_type_id: 'test.always-firing-alert-as-data', + schedule: { interval: '24h' }, + tags: ['test'], + throttle: undefined, + notify_when: 'onActiveAlert', + params: { + index: alertAsDataIndex, + reference: 'test', + }, + actions: [ + { + id: action.id, + group: 'default', + params: {}, + }, + { + id: action.id, + group: 'recovered', + params: {}, + }, + ], + }) + ) + .expect(200); + + objectRemover.add(Spaces.space1.id, rule.id, 'rule', 'alerting'); + + // Run the first time - active + await getRuleEvents({ + id: rule.id, + activeInstance: 2, + retry, + getService, + }); + + await expectNoActionsFired({ + id: rule.id, + supertest, + retry, + }); + }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts index b2196d9ea3724..8c3438f7152a5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts @@ -22,7 +22,7 @@ export const createRule = async ({ overwrites, }: { actionId: string; - pattern: { instance: boolean[] }; + pattern?: { instance: boolean[] }; supertest: SuperTestAgent; objectRemover: ObjectRemover; overwrites?: any; From f544fb05bb6567196812f983416a47f32c39c155 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Mon, 26 Aug 2024 22:25:03 -0400 Subject: [PATCH 17/38] Update renovate config (#191304) ## Summary Update the renovate configuration by migrating deprecated configuration to supported configuration. This was generated using the instructions found in https://docs.renovatebot.com/config-validation/: ```sh npx --yes --package renovate -- renovate-config-validator --strict ```
View full output ``` INFO: Validating renovate.json WARN: Config migration necessary "oldConfig": { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver" ], "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], "enabledManagers": ["npm", "github-actions", "custom.regex"], "baseBranches": ["main", "7.17"], "prConcurrentLimit": 0, "prHourlyLimit": 0, "separateMajorMinor": false, "rangeStrategy": "bump", "semanticCommits": "disabled", "vulnerabilityAlerts": {"enabled": false}, "lockFileMaintenance": {"enabled": false}, "packageRules": [ {"matchDepPatterns": [".*"], "enabled": false}, { "groupName": "chainguard", "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "enabled": true }, { "groupName": "operations actions", "matchManagers": ["github-actions"], "matchPackageNames": [ "actions/checkout", "elastic/github-actions/project-assigner", "hmarr/auto-approve-action", "octokit/graphql-action", "sergeysova/jq-action", "sourenlouv/backport" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "enabled": true }, { "groupName": "@elastic/charts", "matchDepNames": ["@elastic/charts"], "reviewers": ["team:visualizations", "markov00", "nickofthyme"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "Team:Visualizations"], "enabled": true }, { "groupName": "@elastic/elasticsearch", "matchDepNames": ["@elastic/elasticsearch"], "reviewers": ["team:kibana-operations", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:skip", "Team:Operations", "Team:Core" ], "enabled": true }, { "groupName": "@elastic/elasticsearch", "matchDepNames": ["@elastic/elasticsearch"], "reviewers": ["team:kibana-operations", "team:kibana-core"], "matchBaseBranches": ["7.17"], "labels": [ "release_note:skip", "Team:Operations", "Team:Core", "backport:skip" ], "enabled": true }, { "groupName": "LaunchDarkly", "matchDepNames": [ "launchdarkly-js-client-sdk", "@launchdarkly/node-server-sdk", "launchdarkly/find-code-references" ], "reviewers": ["team:kibana-security", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "Team:Security", "Team:Core", "backport:prev-minor" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "APM", "matchDepNames": [ "elastic-apm-node", "@elastic/apm-rum", "@elastic/apm-rum-react" ], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "@elastic/ebt", "matchDepNames": ["@elastic/ebt"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "ansi-regex", "matchDepNames": ["ansi-regex"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenAPI Spec", "matchDepNames": ["@redocly/cli"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "babel", "matchDepNames": ["@types/babel__core", "/^@babel/", "/^babel-plugin/"], "matchDepPatterns": ["^@babel", "^babel-plugin"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "typescript", "matchDepNames": ["typescript", "@types/jsdom"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "prettier", "matchDepNames": [ "prettier", "eslint-plugin-prettier", "eslint-config-prettier" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<3.0", "enabled": true }, { "groupName": "typescript-eslint", "matchDepPatterns": ["^@typescript-eslint"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "eslint-plugin-depend", "matchDepPatterns": ["eslint-plugin-depend"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "polyfills", "matchDepNames": ["core-js", "/polyfill/"], "matchDepPatterns": ["polyfill"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CLI tooling", "matchDepNames": ["listr2"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "vega related modules", "matchDepNames": [ "vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip" ], "reviewers": ["team:kibana-visualizations"], "matchBaseBranches": ["main"], "labels": ["Feature:Vega", "Team:Visualizations"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "cypress", "matchDepPatterns": ["cypress"], "reviewers": ["Team:apm", "Team: SecuritySolution"], "matchBaseBranches": ["main"], "labels": ["buildkite-ci", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "security solution modules", "matchDepNames": ["zod", "langchain"], "reviewers": ["Team: SecuritySolution"], "matchBaseBranches": ["main"], "labels": ["Team: SecuritySolution"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "platform security modules", "matchDepNames": [ "css.escape", "node-forge", "formik", "@types/node-forge", "require-in-the-middle", "tough-cookie", "@types/tough-cookie", "xml-crypto", "@types/xml-crypto", "@kayahr/text-encoding" ], "reviewers": ["team:kibana-security"], "matchBaseBranches": ["main"], "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CodeQL", "matchDepNames": [ "github/codeql-action/analyze", "github/codeql-action/init" ], "reviewers": ["team:kibana-security"], "matchBaseBranches": ["main"], "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "ftr", "matchDepNames": [ "@types/chromedriver", "@types/selenium-webdriver", "chromedriver", "geckodriver", "ms-chromium-edge-driver", "selenium-webdriver" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "scss", "matchDepNames": ["sass-embedded"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "minify", "matchDepNames": ["gulp-terser", "terser"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@testing-library", "matchDepNames": [ "@testing-library/dom", "@testing-library/jest-dom", "@testing-library/react", "@testing-library/react-hooks", "@testing-library/user-event", "@types/testing-library__jest-dom" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "jest", "matchDepNames": [ "@jest/console", "@jest/reporters", "@jest/types", "babel-jest", "expect", "jest", "jest-cli", "jest-config", "jest-diff", "jest-environment-jsdom", "jest-matcher-utils", "jest-mock", "jest-runtime", "jest-snapshot" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@storybook", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "matchDepPatterns": ["^@storybook"], "excludeDepNames": ["@storybook/testing-react"], "labels": [ "Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip" ], "minimumReleaseAge": "7 days", "allowedVersions": "<7.0", "enabled": true }, { "groupName": "@storybook/testing-react", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "matchDepNames": ["@storybook/testing-react"], "labels": [ "Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip" ], "minimumReleaseAge": "7 days", "allowedVersions": "<2.0", "enabled": true }, { "groupName": "react-query", "matchDepNames": [ "@tanstack/react-query", "@tanstack/react-query-devtools" ], "reviewers": [ "team:response-ops", "team:kibana-cloud-security-posture", "team:security-asset-management", "team:fleet", "team:awp-platform", "team:security-onboarding-and-lifecycle-mgt" ], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "react-hook-form", "matchDepNames": ["react-hook-form"], "reviewers": ["team:security-asset-management", "team:uptime"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "redux", "matchDepNames": ["redux", "react-redux"], "reviewers": [ "team:search-kibana", "team:kibana-presentation", "team:kibana-data-discovery", "team:kibana-management", "team:kibana-gis", "team:security-solution" ], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Profiling", "matchDepNames": ["peggy", "@types/dagre"], "reviewers": ["team:obs-ux-infra_services-team"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "TTY Output", "matchDepNames": ["xterm", "byte-size", "@types/byte-size"], "reviewers": ["team:sec-cloudnative-integrations"], "matchBaseBranches": ["main"], "labels": [ "Team: AWP: Visualization", "release_note:skip", "backport:skip" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Cloud Defend", "matchDepNames": ["monaco-yaml"], "reviewers": ["team:sec-cloudnative-integrations"], "matchBaseBranches": ["main"], "labels": [ "Team: Cloud Native Integrations", "release_note:skip", "backport:skip" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "JSON Web Token", "matchDepNames": ["jsonwebtoken"], "reviewers": ["team:response-ops", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "XState", "matchDepNames": ["xstate", "@xstate/{/,}**"], "matchDepPrefixes": ["@xstate/"], "reviewers": ["team:obs-ux-logs-team"], "matchBaseBranches": ["main"], "labels": ["Team:Obs UX Logs", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenTelemetry modules", "matchDepPrefixes": ["@opentelemetry/"], "reviewers": ["team:stack-monitoring"], "matchBaseBranches": ["main"], "labels": ["Team:Monitoring"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "csp", "matchDepNames": ["content-security-policy-parser"], "reviewers": ["team:kibana-security", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:skip", "ci:serverless-test-all" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "AlertingEmails", "matchDepNames": ["nodemailer"], "reviewers": ["team:response-ops"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Kibana ES|QL Team", "matchDepNames": ["recast"], "reviewers": ["team:kibana-esql"], "matchBaseBranches": ["main"], "labels": ["Team:ESQL", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "MSW", "matchPackageNames": ["msw"], "reviewers": ["team:kibana-cloud-security-posture"], "matchBaseBranches": ["main"], "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], "enabled": true }, { "groupName": "re2js", "matchDepNames": ["re2js"], "reviewers": ["team:visualizations", "dej611"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:all-open", "Team:Visualizations" ], "enabled": true }, { "groupName": "Serve swagger docs", "matchDepNames": ["express", "swagger-jsdoc", "swagger-ui-express"], "reviewers": ["team:obs-entities"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "team:obs-entities"], "enabled": true } ], "customManagers": [ { "description": "Update Wolfi base image", "customType": "regex", "fileMatch": [ "^src/dev/build/tasks/os_packages/docker_generator/run\\.ts$" ], "matchStrings": [ "(?docker\\.elastic\\.co/wolfi/chainguard-base):(?[-a-zA-Z0-9.]+)?(?:@(?sha256:[a-fA-F0-9]+))?" ], "datasourceTemplate": "docker" }, { "description": "Update pipelib image", "customType": "regex", "fileMatch": [ "^\\.buildkite/pipeline-resource-definitions/scripts/validate-pipeline-definition\\.sh$", "^\\.buildkite/scripts/steps/checks/renovate\\.sh$" ], "matchStrings": [ "(?docker\\.elastic\\.co/ci-agent-images/pipelib):(?[-a-zA-Z0-9.]+)?(?:@(?sha256:[a-fA-F0-9]+))?" ], "datasourceTemplate": "docker" } ] }, "newConfig": { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver" ], "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], "enabledManagers": ["npm", "github-actions", "custom.regex"], "baseBranches": ["main", "7.17"], "prConcurrentLimit": 0, "prHourlyLimit": 0, "separateMajorMinor": false, "rangeStrategy": "bump", "semanticCommits": "disabled", "vulnerabilityAlerts": {"enabled": false}, "lockFileMaintenance": {"enabled": false}, "packageRules": [ {"enabled": false, "matchDepNames": ["/.*/"]}, { "groupName": "chainguard", "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "enabled": true }, { "groupName": "operations actions", "matchManagers": ["github-actions"], "matchPackageNames": [ "actions/checkout", "elastic/github-actions/project-assigner", "hmarr/auto-approve-action", "octokit/graphql-action", "sergeysova/jq-action", "sourenlouv/backport" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "enabled": true }, { "groupName": "@elastic/charts", "matchDepNames": ["@elastic/charts"], "reviewers": ["team:visualizations", "markov00", "nickofthyme"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "Team:Visualizations"], "enabled": true }, { "groupName": "@elastic/elasticsearch", "matchDepNames": ["@elastic/elasticsearch"], "reviewers": ["team:kibana-operations", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:skip", "Team:Operations", "Team:Core" ], "enabled": true }, { "groupName": "@elastic/elasticsearch", "matchDepNames": ["@elastic/elasticsearch"], "reviewers": ["team:kibana-operations", "team:kibana-core"], "matchBaseBranches": ["7.17"], "labels": [ "release_note:skip", "Team:Operations", "Team:Core", "backport:skip" ], "enabled": true }, { "groupName": "LaunchDarkly", "matchDepNames": [ "launchdarkly-js-client-sdk", "@launchdarkly/node-server-sdk", "launchdarkly/find-code-references" ], "reviewers": ["team:kibana-security", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "Team:Security", "Team:Core", "backport:prev-minor" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "APM", "matchDepNames": [ "elastic-apm-node", "@elastic/apm-rum", "@elastic/apm-rum-react" ], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "@elastic/ebt", "matchDepNames": ["@elastic/ebt"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "ansi-regex", "matchDepNames": ["ansi-regex"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenAPI Spec", "matchDepNames": ["@redocly/cli"], "reviewers": ["team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "babel", "matchDepNames": ["@types/babel__core", "/^@babel/", "/^babel-plugin/"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "typescript", "matchDepNames": ["typescript", "@types/jsdom"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "prettier", "matchDepNames": [ "prettier", "eslint-plugin-prettier", "eslint-config-prettier" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<3.0", "enabled": true }, { "groupName": "typescript-eslint", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true, "matchDepNames": ["/^@typescript-eslint/"] }, { "groupName": "eslint-plugin-depend", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true, "matchDepNames": ["/eslint-plugin-depend/"] }, { "groupName": "polyfills", "matchDepNames": ["core-js", "/polyfill/"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CLI tooling", "matchDepNames": ["listr2"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "vega related modules", "matchDepNames": [ "vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip" ], "reviewers": ["team:kibana-visualizations"], "matchBaseBranches": ["main"], "labels": ["Feature:Vega", "Team:Visualizations"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "cypress", "reviewers": ["Team:apm", "Team: SecuritySolution"], "matchBaseBranches": ["main"], "labels": ["buildkite-ci", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true, "matchDepNames": ["/cypress/"] }, { "groupName": "security solution modules", "matchDepNames": ["zod", "langchain"], "reviewers": ["Team: SecuritySolution"], "matchBaseBranches": ["main"], "labels": ["Team: SecuritySolution"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "platform security modules", "matchDepNames": [ "css.escape", "node-forge", "formik", "@types/node-forge", "require-in-the-middle", "tough-cookie", "@types/tough-cookie", "xml-crypto", "@types/xml-crypto", "@kayahr/text-encoding" ], "reviewers": ["team:kibana-security"], "matchBaseBranches": ["main"], "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CodeQL", "matchDepNames": [ "github/codeql-action/analyze", "github/codeql-action/init" ], "reviewers": ["team:kibana-security"], "matchBaseBranches": ["main"], "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "ftr", "matchDepNames": [ "@types/chromedriver", "@types/selenium-webdriver", "chromedriver", "geckodriver", "ms-chromium-edge-driver", "selenium-webdriver" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "scss", "matchDepNames": ["sass-embedded"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "minify", "matchDepNames": ["gulp-terser", "terser"], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@testing-library", "matchDepNames": [ "@testing-library/dom", "@testing-library/jest-dom", "@testing-library/react", "@testing-library/react-hooks", "@testing-library/user-event", "@types/testing-library__jest-dom" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "jest", "matchDepNames": [ "@jest/console", "@jest/reporters", "@jest/types", "babel-jest", "expect", "jest", "jest-cli", "jest-config", "jest-diff", "jest-environment-jsdom", "jest-matcher-utils", "jest-mock", "jest-runtime", "jest-snapshot" ], "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@storybook", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "labels": [ "Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip" ], "minimumReleaseAge": "7 days", "allowedVersions": "<7.0", "enabled": true, "matchDepNames": ["/^@storybook/", "!@storybook/testing-react"] }, { "groupName": "@storybook/testing-react", "reviewers": ["team:kibana-operations"], "matchBaseBranches": ["main"], "matchDepNames": ["@storybook/testing-react"], "labels": [ "Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip" ], "minimumReleaseAge": "7 days", "allowedVersions": "<2.0", "enabled": true }, { "groupName": "react-query", "matchDepNames": [ "@tanstack/react-query", "@tanstack/react-query-devtools" ], "reviewers": [ "team:response-ops", "team:kibana-cloud-security-posture", "team:security-asset-management", "team:fleet", "team:awp-platform", "team:security-onboarding-and-lifecycle-mgt" ], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "react-hook-form", "matchDepNames": ["react-hook-form"], "reviewers": ["team:security-asset-management", "team:uptime"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "redux", "matchDepNames": ["redux", "react-redux"], "reviewers": [ "team:search-kibana", "team:kibana-presentation", "team:kibana-data-discovery", "team:kibana-management", "team:kibana-gis", "team:security-solution" ], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Profiling", "matchDepNames": ["peggy", "@types/dagre"], "reviewers": ["team:obs-ux-infra_services-team"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "TTY Output", "matchDepNames": ["xterm", "byte-size", "@types/byte-size"], "reviewers": ["team:sec-cloudnative-integrations"], "matchBaseBranches": ["main"], "labels": [ "Team: AWP: Visualization", "release_note:skip", "backport:skip" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Cloud Defend", "matchDepNames": ["monaco-yaml"], "reviewers": ["team:sec-cloudnative-integrations"], "matchBaseBranches": ["main"], "labels": [ "Team: Cloud Native Integrations", "release_note:skip", "backport:skip" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "JSON Web Token", "matchDepNames": ["jsonwebtoken"], "reviewers": ["team:response-ops", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "XState", "matchDepNames": ["xstate", "@xstate/{/,}**"], "reviewers": ["team:obs-ux-logs-team"], "matchBaseBranches": ["main"], "labels": ["Team:Obs UX Logs", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenTelemetry modules", "reviewers": ["team:stack-monitoring"], "matchBaseBranches": ["main"], "labels": ["Team:Monitoring"], "minimumReleaseAge": "7 days", "enabled": true, "matchDepNames": ["@opentelemetry/{/,}**"] }, { "groupName": "csp", "matchDepNames": ["content-security-policy-parser"], "reviewers": ["team:kibana-security", "team:kibana-core"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:skip", "ci:serverless-test-all" ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "AlertingEmails", "matchDepNames": ["nodemailer"], "reviewers": ["team:response-ops"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Kibana ES|QL Team", "matchDepNames": ["recast"], "reviewers": ["team:kibana-esql"], "matchBaseBranches": ["main"], "labels": ["Team:ESQL", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "MSW", "matchPackageNames": ["msw"], "reviewers": ["team:kibana-cloud-security-posture"], "matchBaseBranches": ["main"], "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], "enabled": true }, { "groupName": "re2js", "matchDepNames": ["re2js"], "reviewers": ["team:visualizations", "dej611"], "matchBaseBranches": ["main"], "labels": [ "release_note:skip", "backport:all-open", "Team:Visualizations" ], "enabled": true }, { "groupName": "Serve swagger docs", "matchDepNames": ["express", "swagger-jsdoc", "swagger-ui-express"], "reviewers": ["team:obs-entities"], "matchBaseBranches": ["main"], "labels": ["release_note:skip", "team:obs-entities"], "enabled": true } ], "customManagers": [ { "description": "Update Wolfi base image", "customType": "regex", "fileMatch": [ "^src/dev/build/tasks/os_packages/docker_generator/run\\.ts$" ], "matchStrings": [ "(?docker\\.elastic\\.co/wolfi/chainguard-base):(?[-a-zA-Z0-9.]+)?(?:@(?sha256:[a-fA-F0-9]+))?" ], "datasourceTemplate": "docker" }, { "description": "Update pipelib image", "customType": "regex", "fileMatch": [ "^\\.buildkite/pipeline-resource-definitions/scripts/validate-pipeline-definition\\.sh$", "^\\.buildkite/scripts/steps/checks/renovate\\.sh$" ], "matchStrings": [ "(?docker\\.elastic\\.co/ci-agent-images/pipelib):(?[-a-zA-Z0-9.]+)?(?:@(?sha256:[a-fA-F0-9]+))?" ], "datasourceTemplate": "docker" } ] } ```
------ This PR has 2 commits: 1. `7039eaf25b5334ca798e9c16ba75b5d5511c8138`: contains only whitespace changes, in order to make the resulting diff easier to digest. 2. `da12693c107e3e2b6aeacb21c75812b1a2200497`: the actual config migration. --- renovate.json | 843 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 654 insertions(+), 189 deletions(-) diff --git a/renovate.json b/renovate.json index 774dce52e3515..233505d4012de 100644 --- a/renovate.json +++ b/renovate.json @@ -1,9 +1,24 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver"], - "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], - "enabledManagers": ["npm", "github-actions", "custom.regex", "devcontainer"], - "baseBranches": ["main", "7.17"], + "extends": [ + "config:recommended", + "helpers:pinGitHubActionDigests", + "helpers:pinGitHubActionDigestsToSemver" + ], + "ignorePaths": [ + "**/__fixtures__/**", + "**/fixtures/**" + ], + "enabledManagers": [ + "npm", + "github-actions", + "custom.regex", + "devcontainer" + ], + "baseBranches": [ + "main", + "7.17" + ], "prConcurrentLimit": 0, "prHourlyLimit": 0, "separateMajorMinor": false, @@ -17,28 +32,51 @@ }, "packageRules": [ { - "matchDepPatterns": [".*"], - "enabled": false + "enabled": false, + "matchDepNames": [ + "/.*/" + ] }, { "groupName": "devcontainer", - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip", "backport:current-major"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip", + "backport:current-major" + ], "enabled": true, - "matchManagers": ["devcontainer"] + "matchManagers": [ + "devcontainer" + ] }, { "groupName": "chainguard", - "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchPackageNames": [ + "docker.elastic.co/wolfi/chainguard-base" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "enabled": true }, { "groupName": "operations actions", - "matchManagers": ["github-actions"], + "matchManagers": [ + "github-actions" + ], "matchPackageNames": [ "actions/checkout", "elastic/github-actions/project-assigner", @@ -47,168 +85,367 @@ "sergeysova/jq-action", "sourenlouv/backport" ], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "backport:all-open", + "release_note:skip" + ], "enabled": true }, { "groupName": "@elastic/charts", - "matchDepNames": ["@elastic/charts"], - "reviewers": ["team:visualizations", "markov00", "nickofthyme"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "Team:Visualizations"], + "matchDepNames": [ + "@elastic/charts" + ], + "reviewers": [ + "team:visualizations", + "markov00", + "nickofthyme" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "Team:Visualizations" + ], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": ["@elastic/elasticsearch"], - "reviewers": ["team:kibana-operations", "team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "Team:Operations", "Team:Core"], + "matchDepNames": [ + "@elastic/elasticsearch" + ], + "reviewers": [ + "team:kibana-operations", + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "Team:Operations", + "Team:Core" + ], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": ["@elastic/elasticsearch"], - "reviewers": ["team:kibana-operations", "team:kibana-core"], - "matchBaseBranches": ["7.17"], - "labels": ["release_note:skip", "Team:Operations", "Team:Core", "backport:skip"], + "matchDepNames": [ + "@elastic/elasticsearch" + ], + "reviewers": [ + "team:kibana-operations", + "team:kibana-core" + ], + "matchBaseBranches": [ + "7.17" + ], + "labels": [ + "release_note:skip", + "Team:Operations", + "Team:Core", + "backport:skip" + ], "enabled": true }, { "groupName": "LaunchDarkly", - "matchDepNames": ["launchdarkly-js-client-sdk", "@launchdarkly/node-server-sdk", "launchdarkly/find-code-references"], - "reviewers": ["team:kibana-security", "team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "Team:Security", "Team:Core", "backport:prev-minor"], + "matchDepNames": [ + "launchdarkly-js-client-sdk", + "@launchdarkly/node-server-sdk", + "launchdarkly/find-code-references" + ], + "reviewers": [ + "team:kibana-security", + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Security", + "Team:Core", + "backport:prev-minor" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "APM", - "matchDepNames": ["elastic-apm-node", "@elastic/apm-rum", "@elastic/apm-rum-react"], - "reviewers": ["team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "Team:Core", "backport:skip"], + "matchDepNames": [ + "elastic-apm-node", + "@elastic/apm-rum", + "@elastic/apm-rum-react" + ], + "reviewers": [ + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Core", + "backport:skip" + ], "enabled": true }, { "groupName": "@elastic/ebt", - "matchDepNames": ["@elastic/ebt"], - "reviewers": ["team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "Team:Core", "backport:skip"], + "matchDepNames": [ + "@elastic/ebt" + ], + "reviewers": [ + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Core", + "backport:skip" + ], "enabled": true }, { "groupName": "ansi-regex", - "matchDepNames": ["ansi-regex"], - "reviewers": ["team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "Team:Core", "backport:skip"], + "matchDepNames": [ + "ansi-regex" + ], + "reviewers": [ + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Core", + "backport:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenAPI Spec", - "matchDepNames": ["@redocly/cli"], - "reviewers": ["team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "Team:Core", "backport:skip"], + "matchDepNames": [ + "@redocly/cli" + ], + "reviewers": [ + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Core", + "backport:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "babel", - "matchDepNames": ["@types/babel__core"], - "matchDepPatterns": ["^@babel", "^babel-plugin"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchDepNames": [ + "@types/babel__core", + "/^@babel/", + "/^babel-plugin/" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "typescript", - "matchDepNames": ["typescript", "@types/jsdom"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchDepNames": [ + "typescript", + "@types/jsdom" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "prettier", - "matchDepNames": ["prettier", "eslint-plugin-prettier", "eslint-config-prettier"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchDepNames": [ + "prettier", + "eslint-plugin-prettier", + "eslint-config-prettier" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "allowedVersions": "<3.0", "enabled": true }, { "groupName": "typescript-eslint", - "matchDepPatterns": ["^@typescript-eslint"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", - "enabled": true + "enabled": true, + "matchDepNames": [ + "/^@typescript-eslint/" + ] }, { "groupName": "eslint-plugin-depend", - "matchDepPatterns": ["eslint-plugin-depend"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", - "enabled": true + "enabled": true, + "matchDepNames": [ + "/eslint-plugin-depend/" + ] }, { "groupName": "polyfills", - "matchDepNames": ["core-js"], - "matchDepPatterns": ["polyfill"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchDepNames": [ + "core-js", + "/polyfill/" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CLI tooling", - "matchDepNames": ["listr2"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], + "matchDepNames": [ + "listr2" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "backport:all-open", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "vega related modules", - "matchDepNames": ["vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip"], - "reviewers": ["team:kibana-visualizations"], - "matchBaseBranches": ["main"], - "labels": ["Feature:Vega", "Team:Visualizations"], + "matchDepNames": [ + "vega", + "vega-lite", + "vega-schema-url-parser", + "vega-tooltip" + ], + "reviewers": [ + "team:kibana-visualizations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Feature:Vega", + "Team:Visualizations" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "cypress", - "matchDepPatterns": ["cypress"], - "reviewers": ["Team:apm", "Team: SecuritySolution"], - "matchBaseBranches": ["main"], - "labels": ["buildkite-ci", "ci:all-cypress-suites"], + "reviewers": [ + "Team:apm", + "Team: SecuritySolution" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "buildkite-ci", + "ci:all-cypress-suites" + ], "minimumReleaseAge": "7 days", - "enabled": true + "enabled": true, + "matchDepNames": [ + "/cypress/" + ] }, { "groupName": "security solution modules", - "matchDepNames": ["zod", "langchain"], - "reviewers": ["Team: SecuritySolution"], - "matchBaseBranches": ["main"], - "labels": ["Team: SecuritySolution"], + "matchDepNames": [ + "zod", + "langchain" + ], + "reviewers": [ + "Team: SecuritySolution" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team: SecuritySolution" + ], "minimumReleaseAge": "7 days", "enabled": true }, @@ -226,9 +463,17 @@ "@types/xml-crypto", "@kayahr/text-encoding" ], - "reviewers": ["team:kibana-security"], - "matchBaseBranches": ["main"], - "labels": ["Team:Security", "release_note:skip", "backport:all-open"], + "reviewers": [ + "team:kibana-security" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Security", + "release_note:skip", + "backport:all-open" + ], "minimumReleaseAge": "7 days", "enabled": true }, @@ -238,9 +483,17 @@ "github/codeql-action/analyze", "github/codeql-action/init" ], - "reviewers": ["team:kibana-security"], - "matchBaseBranches": ["main"], - "labels": ["Team:Security", "release_note:skip", "backport:all-open"], + "reviewers": [ + "team:kibana-security" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Security", + "release_note:skip", + "backport:all-open" + ], "minimumReleaseAge": "7 days", "enabled": true }, @@ -254,27 +507,54 @@ "ms-chromium-edge-driver", "selenium-webdriver" ], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "scss", - "matchDepNames": ["sass-embedded"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip", "backport:all-open"], + "matchDepNames": [ + "sass-embedded" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip", + "backport:all-open" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "minify", - "matchDepNames": ["gulp-terser", "terser"], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "matchDepNames": [ + "gulp-terser", + "terser" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, @@ -288,9 +568,16 @@ "@testing-library/user-event", "@types/testing-library__jest-dom" ], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, @@ -312,36 +599,68 @@ "jest-runtime", "jest-snapshot" ], - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "labels": ["Team:Operations", "release_note:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@storybook", - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "matchDepPatterns": ["^@storybook"], - "excludeDepNames": ["@storybook/testing-react"], - "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "release_note:skip", + "ci:build-storybooks", + "backport:skip" + ], "minimumReleaseAge": "7 days", "allowedVersions": "<7.0", - "enabled": true + "enabled": true, + "matchDepNames": [ + "/^@storybook/", + "!@storybook/testing-react" + ] }, { "groupName": "@storybook/testing-react", - "reviewers": ["team:kibana-operations"], - "matchBaseBranches": ["main"], - "matchDepNames": ["@storybook/testing-react"], - "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "matchDepNames": [ + "@storybook/testing-react" + ], + "labels": [ + "Team:Operations", + "release_note:skip", + "ci:build-storybooks", + "backport:skip" + ], "minimumReleaseAge": "7 days", "allowedVersions": "<2.0", "enabled": true }, { "groupName": "react-query", - "matchDepNames": ["@tanstack/react-query", "@tanstack/react-query-devtools"], + "matchDepNames": [ + "@tanstack/react-query", + "@tanstack/react-query-devtools" + ], "reviewers": [ "team:response-ops", "team:kibana-cloud-security-posture", @@ -350,23 +669,43 @@ "team:awp-platform", "team:security-onboarding-and-lifecycle-mgt" ], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "ci:all-cypress-suites" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "react-hook-form", - "matchDepNames": ["react-hook-form"], - "reviewers": ["team:security-asset-management", "team:uptime"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], + "matchDepNames": [ + "react-hook-form" + ], + "reviewers": [ + "team:security-asset-management", + "team:uptime" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "ci:all-cypress-suites" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "redux", - "matchDepNames": ["redux", "react-redux"], + "matchDepNames": [ + "redux", + "react-redux" + ], "reviewers": [ "team:search-kibana", "team:kibana-presentation", @@ -375,115 +714,241 @@ "team:kibana-gis", "team:security-solution" ], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "ci:all-cypress-suites" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Profiling", - "matchDepNames": ["peggy", "@types/dagre"], - "reviewers": ["team:obs-ux-infra_services-team"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip"], + "matchDepNames": [ + "peggy", + "@types/dagre" + ], + "reviewers": [ + "team:obs-ux-infra_services-team" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "TTY Output", - "matchDepNames": ["xterm", "byte-size", "@types/byte-size"], - "reviewers": ["team:sec-cloudnative-integrations"], - "matchBaseBranches": ["main"], - "labels": ["Team: AWP: Visualization", "release_note:skip", "backport:skip"], + "matchDepNames": [ + "xterm", + "byte-size", + "@types/byte-size" + ], + "reviewers": [ + "team:sec-cloudnative-integrations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team: AWP: Visualization", + "release_note:skip", + "backport:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Cloud Defend", - "matchDepNames": ["monaco-yaml"], - "reviewers": ["team:sec-cloudnative-integrations"], - "matchBaseBranches": ["main"], - "labels": ["Team: Cloud Native Integrations", "release_note:skip", "backport:skip"], + "matchDepNames": [ + "monaco-yaml" + ], + "reviewers": [ + "team:sec-cloudnative-integrations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team: Cloud Native Integrations", + "release_note:skip", + "backport:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "JSON Web Token", - "matchDepNames": ["jsonwebtoken"], - "reviewers": ["team:response-ops", "team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:all-open"], + "matchDepNames": [ + "jsonwebtoken" + ], + "reviewers": [ + "team:response-ops", + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:all-open" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "XState", - "matchDepNames": ["xstate"], - "matchDepPrefixes": ["@xstate/"], - "reviewers": ["team:obs-ux-logs-team"], - "matchBaseBranches": ["main"], - "labels": ["Team:Obs UX Logs", "release_note:skip"], + "matchDepNames": [ + "xstate", + "@xstate/{/,}**" + ], + "reviewers": [ + "team:obs-ux-logs-team" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Obs UX Logs", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenTelemetry modules", - "matchDepPrefixes": ["@opentelemetry/"], - "reviewers": ["team:stack-monitoring"], - "matchBaseBranches": ["main"], - "labels": ["Team:Monitoring"], + "reviewers": [ + "team:stack-monitoring" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Monitoring" + ], "minimumReleaseAge": "7 days", - "enabled": true + "enabled": true, + "matchDepNames": [ + "@opentelemetry/{/,}**" + ] }, { "groupName": "csp", - "matchDepNames": ["content-security-policy-parser"], - "reviewers": ["team:kibana-security", "team:kibana-core"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:skip", "ci:serverless-test-all"], + "matchDepNames": [ + "content-security-policy-parser" + ], + "reviewers": [ + "team:kibana-security", + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:skip", + "ci:serverless-test-all" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "AlertingEmails", - "matchDepNames": ["nodemailer"], - "reviewers": ["team:response-ops"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:prev-minor"], + "matchDepNames": [ + "nodemailer" + ], + "reviewers": [ + "team:response-ops" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:prev-minor" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Kibana ES|QL Team", - "matchDepNames": ["recast"], - "reviewers": ["team:kibana-esql"], - "matchBaseBranches": ["main"], - "labels": ["Team:ESQL", "release_note:skip"], + "matchDepNames": [ + "recast" + ], + "reviewers": [ + "team:kibana-esql" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:ESQL", + "release_note:skip" + ], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "MSW", - "matchPackageNames": ["msw"], - "reviewers": ["team:kibana-cloud-security-posture"], - "matchBaseBranches": ["main"], - "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], + "matchPackageNames": [ + "msw" + ], + "reviewers": [ + "team:kibana-cloud-security-posture" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team: Cloud Security", + "release_note:skip", + "backport:skip" + ], "enabled": true }, { "groupName": "re2js", - "matchDepNames": ["re2js"], - "reviewers": ["team:visualizations", "dej611"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "backport:all-open", "Team:Visualizations"], + "matchDepNames": [ + "re2js" + ], + "reviewers": [ + "team:visualizations", + "dej611" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "backport:all-open", + "Team:Visualizations" + ], "enabled": true }, { "groupName": "Serve swagger docs", - "matchDepNames": ["express", "swagger-jsdoc", "swagger-ui-express"], - "reviewers": ["team:obs-entities"], - "matchBaseBranches": ["main"], - "labels": ["release_note:skip", "team:obs-entities"], + "matchDepNames": [ + "express", + "swagger-jsdoc", + "swagger-ui-express" + ], + "reviewers": [ + "team:obs-entities" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "team:obs-entities" + ], "enabled": true } ], @@ -512,4 +977,4 @@ "datasourceTemplate": "docker" } ] -} +} \ No newline at end of file From 985468064a2e92e92eab461275b3f7b8d756aaec Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:53:11 +1000 Subject: [PATCH 18/38] [api-docs] 2024-08-27 Daily api_docs build (#191381) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/812 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- .../ai_assistant_management_selection.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_quality.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/dataset_quality.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/discover_shared.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/entities_data_access.mdx | 2 +- api_docs/entity_manager.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/esql.mdx | 2 +- api_docs/esql_data_grid.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_annotation_listing.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/fields_metadata.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/inference.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/ingest_pipelines.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/integration_assistant.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/investigate.mdx | 2 +- api_docs/investigate_app.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_actions_types.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_log_pattern_analysis.mdx | 2 +- api_docs/kbn_aiops_log_rate_analysis.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_comparators.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerting_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_grouping.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_collection_utils.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_data_view.mdx | 2 +- api_docs/kbn_apm_synthtrace.devdocs.json | 32 ++++++++++ api_docs/kbn_apm_synthtrace.mdx | 4 +- .../kbn_apm_synthtrace_client.devdocs.json | 44 +++++++++++++- api_docs/kbn_apm_synthtrace_client.mdx | 4 +- api_docs/kbn_apm_types.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_avc_banner.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bfetch_error.mdx | 2 +- api_docs/kbn_calculate_auto.mdx | 2 +- .../kbn_calculate_width_from_char_count.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cbor.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mock.mdx | 2 +- api_docs/kbn_code_owners.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...ent_management_content_insights_public.mdx | 2 +- ...ent_management_content_insights_server.mdx | 2 +- ...bn_content_management_favorites_public.mdx | 2 +- ...bn_content_management_favorites_server.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...tent_management_table_list_view_common.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- .../kbn_content_management_user_profiles.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.devdocs.json | 8 +++ api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- .../kbn_core_plugins_contracts_browser.mdx | 2 +- .../kbn_core_plugins_contracts_server.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_security_browser.mdx | 2 +- .../kbn_core_security_browser_internal.mdx | 2 +- api_docs/kbn_core_security_browser_mocks.mdx | 2 +- api_docs/kbn_core_security_common.mdx | 2 +- api_docs/kbn_core_security_server.mdx | 2 +- .../kbn_core_security_server_internal.mdx | 2 +- api_docs/kbn_core_security_server_mocks.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_browser.mdx | 2 +- ...kbn_core_user_profile_browser_internal.mdx | 2 +- .../kbn_core_user_profile_browser_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_common.mdx | 2 +- api_docs/kbn_core_user_profile_server.mdx | 2 +- .../kbn_core_user_profile_server_internal.mdx | 2 +- .../kbn_core_user_profile_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_custom_icons.mdx | 2 +- api_docs/kbn_custom_integrations.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_forge.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_data_stream_adapter.mdx | 2 +- api_docs/kbn_data_view_utils.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_fleet.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_deeplinks_security.mdx | 2 +- api_docs/kbn_deeplinks_shared.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- ...bn_ecs_data_quality_dashboard.devdocs.json | 26 ++++---- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_agent_utils.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- api_docs/kbn_elastic_assistant_common.mdx | 2 +- api_docs/kbn_entities_schema.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_esql_ast.mdx | 2 +- api_docs/kbn_esql_utils.mdx | 2 +- api_docs/kbn_esql_validation_autocomplete.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_field_utils.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_formatters.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- .../kbn_ftr_common_functional_ui_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_grid_layout.mdx | 2 +- api_docs/kbn_grouping.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_index_management.mdx | 2 +- api_docs/kbn_inference_integration_flyout.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_investigation_shared.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_ipynb.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_json_schemas.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_lens_formula_docs.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_content_badge.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_cancellable_search.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- api_docs/kbn_ml_chi2test.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_time_buckets.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_ui_actions.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_mock_idp_utils.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- .../kbn_observability_alerting_rule_utils.mdx | 2 +- .../kbn_observability_alerting_test_data.mdx | 2 +- ...ility_get_padded_alert_time_range_util.mdx | 2 +- api_docs/kbn_openapi_bundler.mdx | 2 +- api_docs/kbn_openapi_generator.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_panel_loader.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_check.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_presentation_containers.mdx | 2 +- api_docs/kbn_presentation_publishing.mdx | 2 +- api_docs/kbn_profiling_utils.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_hooks.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_recently_accessed.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_reporting_csv_share_panel.mdx | 2 +- api_docs/kbn_reporting_export_types_csv.mdx | 2 +- .../kbn_reporting_export_types_csv_common.mdx | 2 +- api_docs/kbn_reporting_export_types_pdf.mdx | 2 +- .../kbn_reporting_export_types_pdf_common.mdx | 2 +- api_docs/kbn_reporting_export_types_png.mdx | 2 +- .../kbn_reporting_export_types_png_common.mdx | 2 +- api_docs/kbn_reporting_mocks_server.mdx | 2 +- api_docs/kbn_reporting_public.mdx | 2 +- api_docs/kbn_reporting_server.mdx | 2 +- api_docs/kbn_resizable_layout.mdx | 2 +- .../kbn_response_ops_feature_flag_service.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rollup.mdx | 2 +- api_docs/kbn_router_to_openapispec.mdx | 2 +- api_docs/kbn_router_utils.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_screenshotting_server.mdx | 2 +- api_docs/kbn_search_api_panels.mdx | 2 +- api_docs/kbn_search_connectors.mdx | 2 +- api_docs/kbn_search_errors.mdx | 2 +- api_docs/kbn_search_index_documents.mdx | 2 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_search_types.mdx | 2 +- api_docs/kbn_security_api_key_management.mdx | 2 +- api_docs/kbn_security_authorization_core.mdx | 2 +- api_docs/kbn_security_form_components.mdx | 2 +- api_docs/kbn_security_hardening.mdx | 2 +- api_docs/kbn_security_plugin_types_common.mdx | 2 +- api_docs/kbn_security_plugin_types_public.mdx | 2 +- api_docs/kbn_security_plugin_types_server.mdx | 2 +- .../kbn_security_role_management_model.mdx | 2 +- ...kbn_security_solution_distribution_bar.mdx | 2 +- api_docs/kbn_security_solution_features.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- .../kbn_server_route_repository_client.mdx | 2 +- .../kbn_server_route_repository_utils.mdx | 2 +- api_docs/kbn_serverless_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- ...n_shared_ux_chrome_navigation.devdocs.json | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_error_boundary.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_tabbed_modal.mdx | 2 +- api_docs/kbn_shared_ux_table_persist.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_predicates.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_synthetics_e2e.mdx | 2 +- api_docs/kbn_synthetics_private_location.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_eui_helpers.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_timerange.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_triggers_actions_ui_types.mdx | 2 +- api_docs/kbn_try_in_console.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_unsaved_changes_badge.mdx | 2 +- api_docs/kbn_unsaved_changes_prompt.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_visualization_utils.mdx | 2 +- api_docs/kbn_xstate_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kbn_zod.mdx | 2 +- api_docs/kbn_zod_helpers.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_data_access.mdx | 2 +- api_docs/logs_explorer.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/metrics_data_access.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/mock_idp_plugin.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_a_i_assistant_app.mdx | 2 +- .../observability_ai_assistant_management.mdx | 2 +- api_docs/observability_logs_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 10 ++-- api_docs/presentation_panel.mdx | 2 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/search_assistant.mdx | 2 +- api_docs/search_connectors.mdx | 2 +- api_docs/search_homepage.mdx | 2 +- api_docs/search_indices.devdocs.json | 59 ++++++++++++++++++- api_docs/search_indices.mdx | 7 ++- api_docs/search_inference_endpoints.mdx | 2 +- api_docs/search_notebooks.mdx | 2 +- api_docs/search_playground.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.devdocs.json | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/slo.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 733 files changed, 892 insertions(+), 750 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index b84ba7dd84b3a..d1b0d67338110 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index cb22a77843b91..00f292e066bd1 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index 64089cad25f56..c693b3de6677e 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index b60c05a02cbcb..be6ca5a797716 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 15721d1622a30..1a063657bc3ca 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 9be2933de550d..13e52a01e4bc3 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 0c4edebdbf8a1..613931cbc07ad 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 5ffc61628b674..c84613332411c 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 52731f2f0bdd4..37d3c259bd800 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index e6f973e1a51f9..f197f466828e3 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 94702b6bcf164..2df911cc5320b 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index f50ac5003f315..51bfb61d58d53 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index ba114295d0a81..c41165e1ee318 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index ee532bc5237f3..78b45c64c1598 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index f4afb9c252539..8924b2865f020 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 78b0873b84b2e..dd48d4ac54d58 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 8a531b9f44f99..62fd884e90c6d 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index c25081bae016a..daccfcd4cf298 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 83327fa549553..68c4aee644c2c 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 33135cde3f83a..c8b738ffc3cac 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 838dfbd71fd7a..be528efc795ec 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 608c0312912e4..485b62c398132 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index f74bca2c1ba31..42e081040e905 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 1e3765e081f7f..ae5937d365d80 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 77b438d48f483..41028dd816d74 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index f0a25fa3029cb..fffe43296211b 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index ce7a1f669b87f..c25bda8943efb 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 73bae082e4d4e..436eede1240b4 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index d5df60f99e43a..89aa3a4b3ae7d 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index dd2aa9902c021..1757889dd6502 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 831cd3b51349e..6a74b9a11ded2 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 90ad97883c711..91ca1bc925b24 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 68b36fa28df1b..f3589688ad057 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 0fb4e2e322485..3f4966f0c7a88 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index f3754bcf48ec3..9d2017898746e 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index e004605ae7346..8e248de96b0bd 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index eb1d64f31aa5c..763357dce3d34 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 594c5f4b84b44..fc1bfd676d94d 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 795794c40a523..8b59717c8123d 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index c57f58885199c..97e775ece5349 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index bc620f666321a..d4ae7cd36f63d 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index 8eff6c0318004..632160f5c04a9 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 10eef49a0ec98..6afa158bf1204 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index b1a14cfaf8eea..34e8d7bd33b28 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index ba8de180d22b5..01c434f316a48 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 71dca536effe9..a86dd58f54772 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/entities_data_access.mdx b/api_docs/entities_data_access.mdx index 03d05d050d427..9bc9b25dd0bfc 100644 --- a/api_docs/entities_data_access.mdx +++ b/api_docs/entities_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entitiesDataAccess title: "entitiesDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the entitiesDataAccess plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entitiesDataAccess'] --- import entitiesDataAccessObj from './entities_data_access.devdocs.json'; diff --git a/api_docs/entity_manager.mdx b/api_docs/entity_manager.mdx index acdbe36bfc16f..b52d2f36b5f39 100644 --- a/api_docs/entity_manager.mdx +++ b/api_docs/entity_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entityManager title: "entityManager" image: https://source.unsplash.com/400x175/?github description: API docs for the entityManager plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entityManager'] --- import entityManagerObj from './entity_manager.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 7cf8a68fe170e..1f1a0ded169d4 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql.mdx b/api_docs/esql.mdx index 22aaf4277eeb0..45d20a01d3834 100644 --- a/api_docs/esql.mdx +++ b/api_docs/esql.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esql title: "esql" image: https://source.unsplash.com/400x175/?github description: API docs for the esql plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esql'] --- import esqlObj from './esql.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index 04404c5cae837..c961d5ad93093 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index ffeacde4fcf16..041bac091bc0b 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index c528c9aa58dff..5079a06b4d0f0 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index e38a3d7853557..57ee52ba4ebb6 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 74e4125aaa010..3472ef2cd2b8e 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 6c58cc7956544..98f8d449dacad 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 39992de941af7..c1ec78c25a48d 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index e2bd17949bd0e..1220aeaeb1197 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index e03224f817a33..63a3bb1804286 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 65a5169418cd5..0f53d63b6f7b6 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index d4500b2146a9a..da30f6abd5686 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index bde0644720f58..66b5f5c744a70 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 49d32e9423c6a..d31843a6fb7cc 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 61f37b5682380..2e80c4db64538 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 55dbd6e9472e0..0c54bc0c3bf43 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 4095619e42335..1807e75907553 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index b86ffe0a0d925..9e08043cf7ad3 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index c4a366db421d5..cad02c831acd9 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 8448a1db11130..91eae5512c2eb 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 08dcfb8b93af2..f67e6ab2de725 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index a1fe1816cdb7e..e985fa2b90bff 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index b3a7dbee05cc0..00c482ea0b345 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 8fa92bdb940dd..d717a1ed62e1e 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 8b0f35d58856e..60537517ae2ec 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index a99aba785800a..93407e10b2fd2 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index ef26985f79e51..b64018272a21b 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 89db514539cf4..eac71905ded56 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 0bea163c766a7..197a35e1a463c 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index bf8624413f9e6..8d281fc9b1aef 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 1189faa67aff3..16d8e69eaeebd 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 808fe8619927c..15a25b6609373 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index db17d1fe2c583..84f5f3de0a2c0 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/inference.mdx b/api_docs/inference.mdx index 41d7972c276b2..fd95715a8cc2f 100644 --- a/api_docs/inference.mdx +++ b/api_docs/inference.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inference title: "inference" image: https://source.unsplash.com/400x175/?github description: API docs for the inference plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inference'] --- import inferenceObj from './inference.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 63b1ae963c74f..19175d82460f5 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index 03a6f52e6efa9..e4cafbc124649 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index a03532520619a..5cf566b63af27 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index aa839fc7b7494..2812e63061be9 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index f627a199e8a5d..4200b4df55f6d 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index af16795ce642b..e9fa8ccba29e8 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/investigate_app.mdx b/api_docs/investigate_app.mdx index 6e6e9573df87a..2348c5fcb711b 100644 --- a/api_docs/investigate_app.mdx +++ b/api_docs/investigate_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigateApp title: "investigateApp" image: https://source.unsplash.com/400x175/?github description: API docs for the investigateApp plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigateApp'] --- import investigateAppObj from './investigate_app.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 65aeb72e525b8..36a873aa0aa93 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index d850afa33c4e5..2b22f5d6fc202 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index bd04e3bd7ce71..879e63ec94b52 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index 72c0d08c39d67..be52419021093 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index 4889f57749563..4eddc3c8f1588 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 27b96fb81397d..f4a1536f13765 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index 586986d6191fa..7fb32ced0de89 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index df3688b8a378b..7429ff247175c 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index 670bd6c095b5f..ca1cc6be7b68c 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 0783cb6d96409..f4446f2c69f3d 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_grouping.mdx b/api_docs/kbn_alerts_grouping.mdx index 0e72fa15a491d..0870d46f2715d 100644 --- a/api_docs/kbn_alerts_grouping.mdx +++ b/api_docs/kbn_alerts_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-grouping title: "@kbn/alerts-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-grouping plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-grouping'] --- import kbnAlertsGroupingObj from './kbn_alerts_grouping.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 0cd3eed21b7a5..f4ae83ee2bb5d 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index e25022fc5f734..b1116871df3d5 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 0e52e03851ef6..9d2cf63cd98a9 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 6e67e7d922532..baab52fcd0c72 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 19ec6459c1db4..5bd1bdf21cf2c 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.devdocs.json b/api_docs/kbn_apm_synthtrace.devdocs.json index d1fa4a2a3ee91..33cbffd896893 100644 --- a/api_docs/kbn_apm_synthtrace.devdocs.json +++ b/api_docs/kbn_apm_synthtrace.devdocs.json @@ -633,6 +633,38 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace", + "id": "def-server.InfraSynthtraceKibanaClient.uninstallSystemPackage", + "type": "Function", + "tags": [], + "label": "uninstallSystemPackage", + "description": [], + "signature": [ + "(packageVersion: string) => Promise" + ], + "path": "packages/kbn-apm-synthtrace/src/lib/infra/infra_synthtrace_kibana_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace", + "id": "def-server.InfraSynthtraceKibanaClient.uninstallSystemPackage.$1", + "type": "string", + "tags": [], + "label": "packageVersion", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace/src/lib/infra/infra_synthtrace_kibana_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 33a5433be9ddf..f2cd1fc825be9 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 51 | 0 | 51 | 9 | +| 53 | 0 | 53 | 9 | ## Server diff --git a/api_docs/kbn_apm_synthtrace_client.devdocs.json b/api_docs/kbn_apm_synthtrace_client.devdocs.json index 269b19c071e85..8f29a85704f03 100644 --- a/api_docs/kbn_apm_synthtrace_client.devdocs.json +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -2724,7 +2724,9 @@ " | ", "K8sContainerMetricsDocument", " | ", - "AWSRdsMetricsDocument" + "AWSRdsMetricsDocument", + " | ", + "K8sNodeMetricsDocument" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts", "deprecated": false, @@ -3135,6 +3137,46 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.infra.k8sNode", + "type": "Function", + "tags": [], + "label": "k8sNode", + "description": [], + "signature": [ + "(name: string, podUid: string) => ", + "K8sNode" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.infra.k8sNode.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_node.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.infra.k8sNode.$2", + "type": "string", + "tags": [], + "label": "podUid", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_node.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ], "initialIsOpen": false diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 6e4b68477a8c1..cd6976985d516 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 201 | 0 | 201 | 31 | +| 204 | 0 | 204 | 33 | ## Common diff --git a/api_docs/kbn_apm_types.mdx b/api_docs/kbn_apm_types.mdx index d6b96a5ab8bd4..7e25637a0387f 100644 --- a/api_docs/kbn_apm_types.mdx +++ b/api_docs/kbn_apm_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-types title: "@kbn/apm-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-types'] --- import kbnApmTypesObj from './kbn_apm_types.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index e8a424253dc37..4a5c5681ea201 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_avc_banner.mdx b/api_docs/kbn_avc_banner.mdx index 739dcd487e764..81e4caa4db02e 100644 --- a/api_docs/kbn_avc_banner.mdx +++ b/api_docs/kbn_avc_banner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-avc-banner title: "@kbn/avc-banner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/avc-banner plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/avc-banner'] --- import kbnAvcBannerObj from './kbn_avc_banner.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index d9a8be53ad56f..83ffe3d48c656 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index 73722d97d721a..0e695ad07bcff 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 42f39d39befa3..56a0eec50a8f2 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index a5df5d5268b8f..91398cbf372ed 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 3157ccf3f1663..83fef34dce621 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cbor.mdx b/api_docs/kbn_cbor.mdx index 67c65a78f25f6..5720f6996dfdf 100644 --- a/api_docs/kbn_cbor.mdx +++ b/api_docs/kbn_cbor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cbor title: "@kbn/cbor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cbor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cbor'] --- import kbnCborObj from './kbn_cbor.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index c207f480071eb..a07787f1fbc3a 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index fb5f8e8dba73b..56b27d69fcece 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 713537094507a..795e67895a493 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index c2085c2f449d0..3e7cdf023bff6 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index e9cee39c3bc4d..80e3fe3bef8b4 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 0fe03f4eef9bf..6f6944f783e90 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 1825225488fb4..622447bc9ecd5 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index 7e76192f8fc4c..85f1b3317f0f0 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index d1cc4af39708c..ee54ac976c335 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index 106a223dcc2f7..b284131e2e21a 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index c9f75f825bc19..acd67820e9cbf 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 7526cc86c5d8a..2fbfe5daa0121 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 33d47fa5e9bd5..8520b4bb8e954 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 305a782cdff12..ab0b8b39b7997 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 6d9410ea61abe..35107047deb46 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_public.mdx b/api_docs/kbn_content_management_content_insights_public.mdx index 29665db46f3ac..25b8de8994840 100644 --- a/api_docs/kbn_content_management_content_insights_public.mdx +++ b/api_docs/kbn_content_management_content_insights_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-public title: "@kbn/content-management-content-insights-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-public plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-public'] --- import kbnContentManagementContentInsightsPublicObj from './kbn_content_management_content_insights_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_server.mdx b/api_docs/kbn_content_management_content_insights_server.mdx index c2090f8a53b2f..a91bfa36b7375 100644 --- a/api_docs/kbn_content_management_content_insights_server.mdx +++ b/api_docs/kbn_content_management_content_insights_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-server title: "@kbn/content-management-content-insights-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-server'] --- import kbnContentManagementContentInsightsServerObj from './kbn_content_management_content_insights_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_public.mdx b/api_docs/kbn_content_management_favorites_public.mdx index 859570658c30b..6c125110686fe 100644 --- a/api_docs/kbn_content_management_favorites_public.mdx +++ b/api_docs/kbn_content_management_favorites_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-public title: "@kbn/content-management-favorites-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-public plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-public'] --- import kbnContentManagementFavoritesPublicObj from './kbn_content_management_favorites_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_server.mdx b/api_docs/kbn_content_management_favorites_server.mdx index 70de1380153ca..c61ad339ebc0b 100644 --- a/api_docs/kbn_content_management_favorites_server.mdx +++ b/api_docs/kbn_content_management_favorites_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-server title: "@kbn/content-management-favorites-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-server'] --- import kbnContentManagementFavoritesServerObj from './kbn_content_management_favorites_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index b5e4f1c046113..6999daa312b6d 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index b56223487fedd..76046ecedaef1 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index b7b5e0b891ca7..e37e79687ed42 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 6a2b46ec8cdb5..3681ee8831136 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_user_profiles.mdx b/api_docs/kbn_content_management_user_profiles.mdx index 589ad5af52eda..8da1564b81135 100644 --- a/api_docs/kbn_content_management_user_profiles.mdx +++ b/api_docs/kbn_content_management_user_profiles.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-user-profiles title: "@kbn/content-management-user-profiles" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-user-profiles plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-user-profiles'] --- import kbnContentManagementUserProfilesObj from './kbn_content_management_user_profiles.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 61bd169963300..4cb63afb92a40 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 1bc742d137657..78f7eb84efd71 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 6a2a17bcc0c1c..abbefe10b46a9 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 25ffddebcd54a..9b231d77175e5 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 786ae526aff21..a45480f32cc93 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index dbfd3c9943b22..9ac1416eb37b8 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 54e0f6aebd344..5bc9d9db9e7e8 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 39938f1f0e13c..81748a4eaf9da 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 7c6c86125017f..99e6f7ed95a38 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index c7a21101d831a..4ff1b45d2732a 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 28aa12a101f99..90369a003db04 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 090641278a27c..8b18bdd944c3b 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index acbd7d86d0c1a..b80bddb5b128c 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 4ef244187214f..0c2868074529e 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index b3fbcc37b64a6..b235d092cd2bd 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index d19b2f3ec9064..64dfef98a4f3e 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 3b314b9b9d232..86ec2b57b7b67 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index d890e9822021e..4f2e8d28523ff 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index c837f16a559b5..52767b383d9c8 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 1f88f35937cf6..6b5767a496834 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 283b22652a787..6c0a063c27065 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index efe029f6cedf1..a1419417c6872 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 26373cb022099..54eac3381fa00 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index a9e7d64c24e89..caa80ce744939 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index f4af3c8945711..82991cfd78825 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 17662a580b545..850127c0c6951 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index e2fdbde59b055..4a7a8dd051701 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 40c6e17eba6fc..b3271d594ffe6 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 2aae2def1f40e..300f618e11429 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index a8e52615d5d2e..343244e747a0b 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 076e2f31cbba8..4423046fa5028 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index b2014680f559a..4dd709e997aaf 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index ddda1e271f6c8..af8c1e840fe65 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 6bb534d138cea..f970fd5519df1 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index c019ad84d5035..5bc6fab00131a 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 6c4de4e755ad6..f34c100d033d2 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 192bdaf578730..8efa9cc15b783 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 21fe31cd626fa..bd58da2512681 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index 5305470441d26..fd91a5d75ddcf 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 219f3f7dcedee..b3952c730cbd7 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 9b980e91148dc..4dc289ee83060 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 64b43dec82b4a..a45de1f50f75c 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 135b5bd52e17f..25e1837f73ebe 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 563f7843c9dbd..7dcb66bdfb339 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 8b1200dc24065..f0873aeae9a46 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index ebfecbdef96fe..5ffef6d967286 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index dc0fe03bbb66f..1210c31594e05 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 8e326d55b4c64..47b6947eaa2c9 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 291d98b7f3596..fc49467aa290c 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index b3f80296a1e68..1ea2637231f60 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index f4fb1b8b62379..6615011e3671e 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index b01952fc0f7ea..8e08648a5df1e 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 175b1f450494e..43f43eb6e7c92 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index ed1c932312684..0756d85c34738 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 0e99a25af2b46..1af4fbadbb98b 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 9770982d8c9fa..3537972f3b5b9 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index c885be97c6f70..f6018a8997841 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 965cdb77e5d64..98c5b513b4ad7 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 556a9582420dd..ebbe78fb88e75 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 83e8cdfae554c..12684496d21aa 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index e269be8a7c596..b67b829b28626 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 9c76df397d47c..2856c722ac306 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 5fea71332b415..877056537d0e1 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 2361dcd4ce4a9..40305d4076732 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 9dc5cb9f4ba9c..72f125b8ea29d 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 4df554ae94f91..ed5ca78ddc8e8 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 97a9dbe5537e3..e5947d81fd6c6 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index a5dbb768016b9..1f8db0d8a5648 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 484a82ab3fe12..87de6afc3b871 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 9f563f9200d3c..0ff64e5fb2d77 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index e12df15c8b306..8e5138f237f33 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -4570,6 +4570,14 @@ "plugin": "rollup", "path": "x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts" }, + { + "plugin": "searchIndices", + "path": "x-pack/plugins/search_indices/server/routes/status.ts" + }, + { + "plugin": "searchIndices", + "path": "x-pack/plugins/search_indices/server/routes/status.ts" + }, { "plugin": "searchInferenceEndpoints", "path": "x-pack/plugins/search_inference_endpoints/server/routes.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index faa43f90cbbd8..55da7f47659f9 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index a7abf37ae338b..c5bac179c2545 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index a687d8297abe1..334266aa40623 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 095d5c3c31683..219e972879623 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 1b6b4a441c837..410e09d20f712 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 8a8862016dc0a..e842d03d48211 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 8eb577ca6d494..1f1016f813882 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 332c3a0466b60..b4f5d3f18ba56 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index a3f544992b55e..b331240f986c8 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 16096e97fe57a..4abfafaac0fa8 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 40cc572e16284..3d16fb52525e7 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index e9a6e0ee2e3cd..2ac6ec6eec448 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 81dada5197aa3..18faa4d7ee048 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index f435853b32975..4c178de68c5eb 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index d0a858815120d..d1274781df178 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 2d6d422e6a7d5..42ef59d4e8fe9 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index a14651f0c7a54..77b4a8b95e19e 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 020d07ff2b3b7..2cc392c023c13 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index d33488808d23c..8ab79b655f46a 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index ff1e46829520a..5a7b43608a23d 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index f1002b29ea7c5..256b5c47368e7 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index a644a6e7e16fc..53b94f64191be 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 817fba3b7d924..aed7cfbfdc30e 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index b4bddd1ecb69a..d6b34efb368a3 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 38c39f36e9440..a14d996e88b08 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 10bda2e234085..4424eec6d6d88 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index b226b85698e79..38e3dec36efdf 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 5c9b26f35e32f..7ba63fc4e4015 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index a9909943ca8f9..1d768b6e2654d 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index fa9d203d1e0d3..dd6fa5f7be57e 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index f53385f84ed9d..d74667afb522d 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index be7ee38da8c10..64fd700def2a2 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 1af1b26b94e38..4134abee4f1ef 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 6f5077ecdad7c..ac0db52af91fa 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 6cbe65cfcfcab..b890ce90ed3a0 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index a66c3a1e8bc2f..8dd9ac49ed57c 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index e4fc3664f3c1b..3890cf2b4f21f 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index 7c32763bb7b18..cecf2378392fb 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 9af156c5d4885..d26af5c3ff7fb 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index c8b8bc0238ced..a4268ddcaf062 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 1f1818b13d28e..f8c9730625e84 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 1b38e2fad95f1..cd0e0b68a49dc 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index e3bb5b61e9b1f..26ebc2421a387 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index e3ae5402183af..25a90fdc8d227 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 6fb02331590ef..4ff5c77ce916e 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 4ac9521f42562..ca449f755492b 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 4538b25d6228b..fc30ca847bfd4 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 583671a12326f..ec1da87fb3620 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 20ace93604b1f..e9b0377c3c715 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 277f624f12d38..ccc6a504fb80e 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 084415c5e6ec9..d02f91af0efc3 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 6a3aa48267813..d6de68dec8b87 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 8dfaa018ace36..e925f5c58a09d 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 15b1c2daff744..bb5cdd9673a52 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 0a8439786d589..859044161ee5d 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index b250ae4c6b60a..f11258261cb8d 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 382e3f08a7da9..b18c1ef66575a 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index bcd95d318ab32..a6287689c0aa9 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index e5bc21524c539..601ada984a49f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 6f6f899bd9132..a84384a614463 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index b1c184840e797..623d97858eee7 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 84cf732c3d303..ecd587fa487bb 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 0ca9fdf5bdf87..6500015899b6c 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index ff6f8d8dbbf88..7fb5702fe6d79 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 62aa3abc7a4f9..0c27a8397688a 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index 01e469ca47d01..8bc3c7ed935e8 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index 0b99c2e733c9b..0d58383363544 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index 1e4fff67c5790..c70b857db551a 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index 8ff209981dfce..45100b7f7459d 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index 705cc7e27b831..4b74c9a28a5d9 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index 4f38c5adb0923..fddd1940b8528 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 24adcbf448aba..1add8c563cd14 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 481e53d9b1ebb..977a119ee22dd 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 1c479d0f7cd9b..f14a21281cd55 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index b9775303740aa..7f933cef04d0f 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 67e277358a829..0e1040e88f886 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 1ab04016a4dfa..3c230369dabc6 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index ee10e22cc9bef..d548b5b3f6950 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 30c4773993e97..5864ba9c263ef 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index fa7de22b30233..310c13b531f52 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 60e64677bcaf7..9ad53365f8f8f 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index d3b9eec651ef6..480af28046991 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index b95990a850eee..89401bbaf4f88 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index f98c71f5a6210..c2dc85da0bc2a 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index 9bc405e89f907..a4daf6a03b792 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 671f61667aa95..2fb4050563b21 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 5f6c353dcae1e..8fe61a5fd852d 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 1702475bce6cc..8ac665cc00b13 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 55b2dd03d0cb2..b960f54080fa8 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 4f025a34da173..0909823486fd3 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index b2f1cf29afabf..d45fa251ca54a 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 9712bac7d5e57..abc774274415d 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index f681d6d03bd20..bc200cc7e5a5a 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 8f453651c2b7c..2eb282d66a231 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index 7ffa9463dd6a5..f3b23040adfa2 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index 7258112f43afb..3dbf7eadf3636 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index 844334cb0fc03..19f9c984b80a0 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index 34182caa73e0a..ff4289de5ba4c 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index 8fee0f5943308..5e94d232e6e0a 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index c8f0d0270f80c..243cce4ec3906 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index eed750453aca7..2afc049d4af3a 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 8ec2e8290c949..2a99a186eb1e2 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index 33aec01f5ab7b..1e21317615285 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 89e83d73868cc..feca7186f57ab 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index f9550e25b24c2..2727940f5d96a 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index daa35a85c9d23..7effa5043c39e 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 02e62eb587dbf..1d813af16a080 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 18436f54fbebb..f5cf1e2c93a31 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index a708dbe051dd0..3a34ca782dbd0 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 7db8631cc1b2d..9b8a9c6d92707 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index 75553df94b517..ea492b42c41c9 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index 0d5857e2e4b0d..eb5f327efbba4 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index e682d44cf3617..b3dee69a77a3c 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index c60a5a5d5a359..b2cc0651c36fd 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index bf85f754704e0..8f87c878d9210 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index e3fc8cf3227ca..36a785292f177 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index d5d027f55713b..403e1f990da63 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 5d952a46c435f..3daff33862051 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 1615c4ef53995..8b1f3f5648581 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 92ad70bce5343..be9ae071f666a 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index dbe4ce7d40c04..07313929d2152 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index ad214571d2a44..98f500d49629e 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 96a2083cc1b8b..0046e85e69576 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 59aac7459c807..e163e5e835c3c 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index 9c3d2ac3d3c86..db8e105b37cf5 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index cc6fa022067a3..e129fa1a192da 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 3d1932533a223..c832a66dda064 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index ef912199961f2..9d17daf67d863 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 426ec8d8aff44..064fdc1dba74d 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 4f3bc6e3d6cdc..5a25941f17f75 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 13899e529cbce..e9e7da44ba4f7 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 12bc9466d10ab..727523f24632e 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index d558d451ab164..af9b82a99ccca 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index ed8b449affefe..c37c010bc0f0b 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index ab094ed51df0b..78bb449ad9c28 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json index 2fe8bd96f7996..031d3c58d56f4 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json +++ b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json @@ -13,7 +13,7 @@ "signature": [ "(indexName: string) => string" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -27,7 +27,7 @@ "signature": [ "string" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -48,7 +48,7 @@ "signature": [ "React.NamedExoticComponent" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.tsx", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/index.tsx", "deprecated": false, "trackAdoption": false, "returnComment": [], @@ -82,7 +82,7 @@ "signature": [ "(phase: string) => string" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase_description.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -96,7 +96,7 @@ "signature": [ "string" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase_description.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -116,7 +116,7 @@ "tags": [], "label": "DATA_QUALITY_DASHBOARD_CONVERSATION_ID", "description": [], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -128,7 +128,7 @@ "tags": [], "label": "DATA_QUALITY_PROMPT_CONTEXT_PILL_TOOLTIP", "description": [], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -142,7 +142,7 @@ "description": [ "The subtitle displayed on the Data Quality dashboard" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -154,7 +154,7 @@ "tags": [], "label": "DATA_QUALITY_SUGGESTED_USER_PROMPT", "description": [], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -171,7 +171,7 @@ "signature": [ "\"https://www.elastic.co/guide/en/ecs/current/ecs-reference.html\"" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -185,7 +185,7 @@ "description": [ "The label displayed for the `ILM phase` combo box on the Data Quality dashboard" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -199,7 +199,7 @@ "description": [ "The tooltip for the `ILM phase` combo box on the Data Quality Dashboard" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -213,7 +213,7 @@ "description": [ "The placeholder for the `ILM phase` combo box on the Data Quality Dashboard" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index a3e1bb5379546..116ac314da649 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index e01e1842ee00a..ecb8be31b9bb9 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 85de938917323..7b70f3b376749 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 67c89e757a4ec..7af819c876f97 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index 6bfd3b9cfe8c9..92dc7af7432dc 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 087883354f35d..f59d42a818657 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 9ce0796819567..a85cb56faac7e 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 447abee5a726f..66b96f0831e53 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 82f7197a1249a..39290298bbf43 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 4fb10c6f614df..7defc402c73ae 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 73c188a70c135..4682902de18c0 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index 7612c024894a3..37f59971731b8 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 1f38616c70383..ceff3fc8ccc09 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index f0d46b9eae74e..2ac95c4c555f1 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 5bc6e7b9a2511..efac234b0c359 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index a90b5b305d093..c6d229e10c886 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index cf987d2b67711..3b3bc618408ac 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 3cc078bda83e2..6f95154559c0f 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 12f05eb000b9c..840b94c6099f2 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 679cf32850c93..c6792527501e6 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_formatters.mdx b/api_docs/kbn_formatters.mdx index 18f6752748f6f..975f0d8b3d26c 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index d9dfeb0aef3d2..9c4ce7cd1354f 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index 70d3d57e4154e..cfebddd016b50 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index a64cbc10de290..b2e6edad7e89d 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 0f3b124ff6bd9..c6d1d68f7a327 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 73403c2c93630..1464998937fe7 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grid_layout.mdx b/api_docs/kbn_grid_layout.mdx index 47f435b8f5de3..d0c7b1be21c63 100644 --- a/api_docs/kbn_grid_layout.mdx +++ b/api_docs/kbn_grid_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grid-layout title: "@kbn/grid-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grid-layout plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grid-layout'] --- import kbnGridLayoutObj from './kbn_grid_layout.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index 239277300f35f..e7e86425d091f 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index f9c85aa76806e..84fda653e2328 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 209e7b05f0c23..f94a968bc8644 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 294ca0294b79e..43784a2c1d056 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 4d2e3c32e9ead..79395e0977fd1 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 9d8aec99c11b7..0ee681a28e023 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 5f001c20ef9ae..42732c51a4ffb 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index a20f133ff517c..28004f413df58 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index f4208a20c12ca..a48990ffc2fa5 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index c2f8204cf1d3f..d139435df3ccf 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index 6959912b3e900..b09f55a9e5f97 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index b93dff85938e5..f8aca0a66b844 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 8c8fc1f53a063..7163a7ed32568 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 996d033af32ce..1fc1c9353910c 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_investigation_shared.mdx b/api_docs/kbn_investigation_shared.mdx index ee6aadb7119c4..ac1933bb3dd1b 100644 --- a/api_docs/kbn_investigation_shared.mdx +++ b/api_docs/kbn_investigation_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-investigation-shared title: "@kbn/investigation-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/investigation-shared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/investigation-shared'] --- import kbnInvestigationSharedObj from './kbn_investigation_shared.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 459e63665dcca..d0f6f93a36eac 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index a90df168512e2..8cec6e84ef1ba 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index e6fd8730c0a5d..df2e9c7a23301 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 8a519e84679b7..1d5b84f2a194e 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 5c32b10250d16..7d3fafdc2db73 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_json_schemas.mdx b/api_docs/kbn_json_schemas.mdx index 7b8e070cfbe87..79935fd0d6a0f 100644 --- a/api_docs/kbn_json_schemas.mdx +++ b/api_docs/kbn_json_schemas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-schemas title: "@kbn/json-schemas" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-schemas plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-schemas'] --- import kbnJsonSchemasObj from './kbn_json_schemas.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index b952c93c25dbc..fe033bedeb821 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 1552f1ad92ee5..d0946f8d0e8ac 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index b553900338629..d8aef714d9841 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 7f2df18f9615e..7a747c70900fa 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 59d1897e70798..e486986a1d1b1 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index e909c658322ed..6df141252cea5 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index 9b8b7a6356d9a..1068a46bdf200 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 248f6e8fdeab5..a86b9da564a60 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 0673378a7500b..482a1affe0697 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index e40b4fed2ce89..b8b07cc1545ad 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index d1db4efa1c320..8c96d2c16a813 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 3602876bd648b..154e4bc028289 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 534b627707916..32813dd411a99 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 77f6fb9dd0e4c..33e21f4205d2f 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index bdec14dfca0d7..ad0c52760082f 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 0b381d6c06bc8..980f56f1f6bb2 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 987d699e38ba6..e4bd5c7f40094 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 74312b3f4909b..89444186dd490 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index d8041dae1352e..6fa1f251b0fc7 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 66aafc4d1f5b8..7f6fab807b5f6 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 80c274bb77521..5baf3af31bdb0 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index 01ca9fc8b289d..caf901e9b2adf 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 2c66aef73b286..0788af076a72c 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 163ee5a1f07ad..37b3106e80804 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index 7b413b1e50fbb..84d5d09e14d3b 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index 01580d9dbe221..21643d9c482c1 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index bf78c4ab935d1..8e5cbb35a5dbc 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index d993b23f8063a..55b4bc658e837 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index e51dea6078496..bbaf79051310f 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 6b379f7700e17..d199168f0da7d 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index df50bc60ab679..e48ca364a2e2d 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 5730a6af5e8b2..91f4f290961ad 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index a31e3dbcc3524..a28085aa353b4 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index 67ec9f8573456..af6d69d9c079c 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 494654cb7959d..b62cc5822b671 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index e4f10dd234ad2..422e5c60201a6 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index f9ea9e7a6b043..cc204d9d961ec 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index e1107dd6f96b6..85197b205df74 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 39e155db59ae8..a431ba883a067 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 98bba83628f86..6e1b48a2118d9 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index 077af7b14882b..def110412a8da 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index 9ff62d3811bda..52b74aed2dcf2 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index 0f37ec567a77f..ef36e23dff982 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index f573d1e4796b1..cb20c7911f56e 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index f1c354337ce4a..a442b83f178de 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 35bd71773d71a..58bf4daeca916 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index a7723cd8add0c..411ec82b9b901 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 6a46e6a311a82..ea636c6b29a2a 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index 4720a3b8316a4..71c861ce26287 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 9cf35d9d7ee29..952cea5ca675a 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index d059058f7fc3a..5a9b39313757f 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 4eca5769841a7..22424f19ffeec 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_rule_utils.mdx b/api_docs/kbn_observability_alerting_rule_utils.mdx index d796616911d37..a7f3bfdfc78de 100644 --- a/api_docs/kbn_observability_alerting_rule_utils.mdx +++ b/api_docs/kbn_observability_alerting_rule_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-rule-utils title: "@kbn/observability-alerting-rule-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-rule-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-rule-utils'] --- import kbnObservabilityAlertingRuleUtilsObj from './kbn_observability_alerting_rule_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 0bd3154f27c0e..45b4e9439fab2 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 266dd9f7c346d..8765cfb145649 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 4ad0e832f364d..49b07d4e68f06 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 81b7fc6d80f90..310ce0e970f3e 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index bceacc2a2ff76..ca28901736540 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 89108a914b0ab..8374769babe61 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index c1f50b93d4dbc..c623a747d1f92 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 73edeafe5ac28..561225ef84ba3 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 0caf98bd1d3c9..d5f9db4ad3c1f 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_check.mdx b/api_docs/kbn_plugin_check.mdx index dca42c43f3356..01125bfede9ef 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 3bf377877f53c..8452e5b00c94b 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 9a49741f5aeb6..fb46a0911997f 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index eddc20fa4edc4..09aca35c8c683 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index aae6f340d0361..6cdbb1935fb7f 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index a63cc0f89d73f..437c50eb2858e 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index bd27c15b5410f..5d9f7f858bf04 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 73261a57a01c1..c5f428f42e982 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index eed38aa52e75d..b86335808cbff 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index b3e497bdc9bde..99051444ed653 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index 4a150d15dfa02..a85b1ebcff194 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 26ab92f81c22c..445f551fc2abd 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 54a1fed835d93..0ae9eb3256543 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 93441411d2d8d..115d877788967 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index 056f7c9079ebf..9efcf620e87fc 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_recently_accessed.mdx b/api_docs/kbn_recently_accessed.mdx index 6b8c56b1e032b..acc96f83709d1 100644 --- a/api_docs/kbn_recently_accessed.mdx +++ b/api_docs/kbn_recently_accessed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-recently-accessed title: "@kbn/recently-accessed" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/recently-accessed plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/recently-accessed'] --- import kbnRecentlyAccessedObj from './kbn_recently_accessed.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 5c0201498b197..8844145592be1 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 2d7443364c09b..7b82fde6b2d1a 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 7e883019c76ae..31c062c852f83 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 8dc7d860f1a0e..87aba75095c4d 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index e3e8e26aea0d6..007843217d3cc 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index 30b6138b40269..e9a64666f306e 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index 0f68dba32ebe4..ef16397fb63c5 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index fbc661c8b5370..84bf57f43d8f9 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index c7c188ef20486..7ffb4afa20566 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index 9531097cc9932..13c7b558aecc9 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index 7f3f1aec541b1..c7df4f2a35bda 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 85982663eaf7e..439f54983a057 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index b7e33d27cf0d1..527ef257e206f 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index 7b9e3a8655b53..b0740c1f0780f 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index ec69948851f9d..04ab2e2a811e6 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 18f6de4e4aaf3..6f0c3bb8d8142 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_feature_flag_service.mdx b/api_docs/kbn_response_ops_feature_flag_service.mdx index 1a3f2dcc14580..a52fa8da91fcc 100644 --- a/api_docs/kbn_response_ops_feature_flag_service.mdx +++ b/api_docs/kbn_response_ops_feature_flag_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-feature-flag-service title: "@kbn/response-ops-feature-flag-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-feature-flag-service plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-feature-flag-service'] --- import kbnResponseOpsFeatureFlagServiceObj from './kbn_response_ops_feature_flag_service.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 35a4b096c8f02..e46de85c77888 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rollup.mdx b/api_docs/kbn_rollup.mdx index 9f9f173ca928b..60b97a50a443a 100644 --- a/api_docs/kbn_rollup.mdx +++ b/api_docs/kbn_rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rollup title: "@kbn/rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rollup plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rollup'] --- import kbnRollupObj from './kbn_rollup.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index 3458414b220e9..d3f48e8d7d757 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 5e496e96ec6c7..4ecb903b21904 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index 53c2259cb08a8..e5b9399563b7b 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 79c8496d40693..49957d43bb9f5 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 36e97618b4693..7bfc27355d592 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_screenshotting_server.mdx b/api_docs/kbn_screenshotting_server.mdx index 253c7b35571bd..a01abd70ab52a 100644 --- a/api_docs/kbn_screenshotting_server.mdx +++ b/api_docs/kbn_screenshotting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-screenshotting-server title: "@kbn/screenshotting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/screenshotting-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/screenshotting-server'] --- import kbnScreenshottingServerObj from './kbn_screenshotting_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 6249103652aa6..652436cc2dc9d 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index d229bd10d7477..22640dd1b1273 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index c4c40d45ca56c..573a1a2d7198c 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 34b28dafddadb..2c623dd2691c8 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index a71aaa3be559a..f33aed11984d7 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 7864d8cbd66c6..4ac282e8ebca1 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_api_key_management.mdx b/api_docs/kbn_security_api_key_management.mdx index 17e9885a60081..f6189b9954646 100644 --- a/api_docs/kbn_security_api_key_management.mdx +++ b/api_docs/kbn_security_api_key_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-api-key-management title: "@kbn/security-api-key-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-api-key-management plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-api-key-management'] --- import kbnSecurityApiKeyManagementObj from './kbn_security_api_key_management.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core.mdx b/api_docs/kbn_security_authorization_core.mdx index f7b825487d2a1..593238d47cb2c 100644 --- a/api_docs/kbn_security_authorization_core.mdx +++ b/api_docs/kbn_security_authorization_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core title: "@kbn/security-authorization-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core'] --- import kbnSecurityAuthorizationCoreObj from './kbn_security_authorization_core.devdocs.json'; diff --git a/api_docs/kbn_security_form_components.mdx b/api_docs/kbn_security_form_components.mdx index f1ed9b56d3a1d..d8387aec6dcb2 100644 --- a/api_docs/kbn_security_form_components.mdx +++ b/api_docs/kbn_security_form_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-form-components title: "@kbn/security-form-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-form-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-form-components'] --- import kbnSecurityFormComponentsObj from './kbn_security_form_components.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index d9f5e78b2756a..02b95af23522a 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index b2978f6438888..998678024f3fd 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 4d2f5bb611e0d..07ec6782f80ed 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index 120bf0d30d555..a06bff9ce2b9e 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_role_management_model.mdx b/api_docs/kbn_security_role_management_model.mdx index 0343e0f75b418..f71acbae2bc64 100644 --- a/api_docs/kbn_security_role_management_model.mdx +++ b/api_docs/kbn_security_role_management_model.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-role-management-model title: "@kbn/security-role-management-model" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-role-management-model plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-role-management-model'] --- import kbnSecurityRoleManagementModelObj from './kbn_security_role_management_model.devdocs.json'; diff --git a/api_docs/kbn_security_solution_distribution_bar.mdx b/api_docs/kbn_security_solution_distribution_bar.mdx index fc91b1b316e1f..5bf0cd8b907ae 100644 --- a/api_docs/kbn_security_solution_distribution_bar.mdx +++ b/api_docs/kbn_security_solution_distribution_bar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-distribution-bar title: "@kbn/security-solution-distribution-bar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-distribution-bar plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-distribution-bar'] --- import kbnSecuritySolutionDistributionBarObj from './kbn_security_solution_distribution_bar.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 81c44abe354d0..88581262f9d03 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index 9239843661fac..d73e565c2d382 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index a982955a7e493..d55725ff48879 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index ee83f6d6b7bf8..7511ee792f431 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 4f42112fe7f12..973abe9ee9af1 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 0924e4bcd60a8..8bafe23e3c1d5 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 3f72d06b3d175..f927981e3c76f 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 08dd31a7b1d25..7144772c9980e 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 30e3a1929e26d..7c6f79c3c27f9 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 553daad76dbe6..534121d95f21b 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index b16b9df52a36c..a358d827360c1 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index d9fbd1e4fe6b5..b8398b5a0ded0 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 0451a8e523198..425198e68fa64 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index f9dfcf22fb37e..318da48ddaa26 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 6ade946cc4a8e..65e5148a9331d 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 754b38b39b00d..6d573f6f5cc89 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 1f056a5301cf7..1eab2bc0ed216 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index d24fdfbe58ca0..3468d526df5e8 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 664cae36af520..05a4daffe5c6a 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 3629ffb8f9495..b1ed44e073df3 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 3ddc46e28fa07..b51cc183606cf 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 09c7feaf982e5..5100bf9f97a93 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index ef83c874ea01e..0d11189a3ef25 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_client.mdx b/api_docs/kbn_server_route_repository_client.mdx index 8f88e347075f9..1d83cb20af3b9 100644 --- a/api_docs/kbn_server_route_repository_client.mdx +++ b/api_docs/kbn_server_route_repository_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-client title: "@kbn/server-route-repository-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-client plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-client'] --- import kbnServerRouteRepositoryClientObj from './kbn_server_route_repository_client.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_utils.mdx b/api_docs/kbn_server_route_repository_utils.mdx index 36ed6127370d7..23891106ad167 100644 --- a/api_docs/kbn_server_route_repository_utils.mdx +++ b/api_docs/kbn_server_route_repository_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-utils title: "@kbn/server-route-repository-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-utils'] --- import kbnServerRouteRepositoryUtilsObj from './kbn_server_route_repository_utils.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 70c46e97c6918..61dafac929b27 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 8b45a4e6737b6..c1e8df59b84d8 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 040df7856ec2f..f70c33f9b8247 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 67ef07788cbd6..442c12f67f7f2 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 45d0bb3cc656b..45be2d441bb8a 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 47bdb86856978..324655fc2323d 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index ab2745a2da9f5..2d3e2564915ef 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index c141c44e19b1d..aae967f68a3f6 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index bd9fd8c26de2e..094a565d51d2d 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 490ba2d862f61..7640ea9e3ca91 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index c6d8d90eb88e9..f5c6d7eea87cb 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 315163a286ee6..73601f7cdaddd 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json b/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json index 3b673465c3055..0adc32c67e70c 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json +++ b/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json @@ -464,7 +464,7 @@ "section": "def-public.ChromeProjectNavigationNode", "text": "ChromeProjectNavigationNode" }, - ", \"id\" | \"children\" | \"path\" | \"sideNavStatus\"> & { title: React.ReactNode; }" + ", \"id\" | \"children\" | \"path\" | \"sideNavStatus\" | \"deepLink\"> & { title: React.ReactNode; }" ], "path": "packages/shared-ux/chrome/navigation/src/ui/components/panel/types.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index de2f1be22a6dc..a377faa46c293 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index dac1ebfe62f01..e32610fbef5e1 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 885f7a5d88226..f57e2086cebd6 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 1a0a3b861ac10..b5a4e93b87331 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 18da152a4c04d..77c95a810948c 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 0157ee52a2d8d..917b5b2333728 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index bac47c40079a4..5ab094f0c0998 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index db312378c9db4..09de63ec5b353 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index a7f54c63c5fa3..a374a425114b1 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 123b0c4dd7935..1bdf08c90ee82 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 60ac414f8edeb..9c5ac68c6c303 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 46b3baf3c23fd..bcf34b6ef3392 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 23948d99702fc..d0aed0b2316a7 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 62e8c04da79cc..5b70a207847bd 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 77db56dfa33fb..7a21b8493ca77 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index a7a327ccc7432..0d1cf5386c1ca 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index e72e0ecb37c1a..b5fac87442b4a 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 2aba4c9459cf1..68321851bfd22 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 77e91d63043bb..710fde66a173c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 7e1da1550d85d..8ee8c50122e85 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index de81d5813964c..dc2d925b0b96f 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 80dbb573d880c..85b6a53f72741 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index a568b1090082a..560c9d0489351 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index e22caec628ae1..428b867b21446 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index a37ea0bbfe7c2..7ffa3ea4574ff 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 76a15059fb893..d5c6199d4cc4c 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index a3e923f15c093..c9cdda33b1e55 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 27401cde7904c..331eb2df1de59 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 760009dad7500..422fe9392d236 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 0b5dca645f91a..68881e7842119 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index e96d133f21681..5a6daa4d86af3 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index f401fa7cf89d2..fb7e548678b19 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index bd59faef8adfd..122ff503d0dd4 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_table_persist.mdx b/api_docs/kbn_shared_ux_table_persist.mdx index e2247279f6a37..24d4af745e4de 100644 --- a/api_docs/kbn_shared_ux_table_persist.mdx +++ b/api_docs/kbn_shared_ux_table_persist.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-table-persist title: "@kbn/shared-ux-table-persist" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-table-persist plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-table-persist'] --- import kbnSharedUxTablePersistObj from './kbn_shared_ux_table_persist.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 11ef6c12b94eb..2856cf3fc5f1a 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 72b3ebab2c17c..de90e78bbe94b 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 1e6abf9706b19..634de2e778da3 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index fada281814b00..5605e34172e00 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 001f510ff1994..7d4509c2d6574 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index ffdc9041d444d..f4db0b702a9ea 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 3581626146783..891f3a4febf4c 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_synthetics_e2e.mdx b/api_docs/kbn_synthetics_e2e.mdx index 45b6c1577fb82..1e145f1a18644 100644 --- a/api_docs/kbn_synthetics_e2e.mdx +++ b/api_docs/kbn_synthetics_e2e.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-e2e title: "@kbn/synthetics-e2e" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-e2e plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-e2e'] --- import kbnSyntheticsE2eObj from './kbn_synthetics_e2e.devdocs.json'; diff --git a/api_docs/kbn_synthetics_private_location.mdx b/api_docs/kbn_synthetics_private_location.mdx index 718efbd33834f..84664ce4602b8 100644 --- a/api_docs/kbn_synthetics_private_location.mdx +++ b/api_docs/kbn_synthetics_private_location.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-private-location title: "@kbn/synthetics-private-location" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-private-location plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-private-location'] --- import kbnSyntheticsPrivateLocationObj from './kbn_synthetics_private_location.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 4d7a91e7d13c2..2eb6cc14c7264 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index fc66dbf3fd9f1..a753af4adf4ba 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index 68818d0dfecbe..2bd09dcd13d06 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 5a62b14a7a1e8..ab7d1a7acb987 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 89c09bc94afa0..e7f8d05bea5f8 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 0e6240a0fb837..7915972645781 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 8d39264a29f21..c4e829ee77482 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 408a5c804ae1b..df8071ff2bae3 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index c5b1773829e85..784c136482a24 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index a26250fbadee1..56f7693e17141 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index cb4dcddf1f0ea..01370ca6bc79c 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 958329f580c32..37b85246847fe 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 67bb7138e583b..24885548ccb26 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 8b775c7b3a3d0..4745ae503988a 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 8323e38495f1f..32a3ec515d213 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index cc3989fb5ab1c..c913eec4ea995 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 752dd87b431a4..6645b4a75c39e 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 27f5002a35ce5..6dda726eb2f67 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index 169b9d77c94cf..8038c5607f6f2 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index 084428560f541..3a8e0c8bc43de 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 12546f6ca591e..3730028bc7038 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 3259cbdbd097e..6e23bd09e9281 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 6919f40add42e..b5360f7bb8a9b 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 70a77382afd08..eba9cbe479837 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 6c094ece8d3d8..d6ea70a2aed24 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 4b276fcbd00b5..6e44040dfdee4 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 85b5594714477..31ad7698725dd 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 63f7e06f6df37..00b688c24559a 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index df658fc822eb5..957417d1279bd 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod.mdx b/api_docs/kbn_zod.mdx index f563a316c8b03..5ff1f59317f45 100644 --- a/api_docs/kbn_zod.mdx +++ b/api_docs/kbn_zod.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod title: "@kbn/zod" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod'] --- import kbnZodObj from './kbn_zod.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index e89dc4eceac4d..6d577c60ef430 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index b21bce542f03c..c875f0cbc61de 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 935d8d675d171..5b84c0375f740 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 59ac323b22040..0645ecabf59f2 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index cbb0b37922179..1f6abaa25bc29 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index bba50fc010c11..c43741ded505e 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 69ca5d7d30dd0..570168a8dd2b8 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 69c306f517a98..82902a4f786e4 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 39602fef559eb..1f5315779511a 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 0f019a4723e84..72b49df0783f8 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 25951ba2f02ca..53a054d43fb22 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 5f7ec53c9ea05..512a59d0cf859 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index e3c6e18426401..0973459c59bba 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index d4c7e55ba1a4b..2eb3bc8027c02 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index a2889eaab7c91..da12ff0f537aa 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 0638e45c5f7ef..d8a4b185e9580 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 2c689ed1ce5aa..65ae1ecf2b5d3 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 0f5ecefa9554f..21983f6f07d17 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 97c8cdbf659c0..5c00beaa1f2f0 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index 617842a6ac4f0..6df6f57ef01ab 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 1538828a8b6e0..12bef159b0c21 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index ab52e0c27e35c..9db57429f5cfd 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 5757fe39a9049..7e06a0834bf6d 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index c380e34e9e2d7..1eb4d22046907 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index a2a7d012f4e47..8d474055489c5 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index c4c3dc5b65a9f..6651a704fce86 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index d57cf14776886..0061af2708ea7 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 8aeaaee5d9178..e39ad294021e9 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index b7a761709fa71..8cbaaa872d4cb 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index bf71ae4d89809..9441612794ad0 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index c06c416cc3da6..2740655f8fa99 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 5fbd19f157ab5..f9dfd904a907b 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index a73c76db72362..df83c7a009637 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index e669a96de64dd..d28a5118490df 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index f0314198d3d0d..2ce6c1982def4 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index fb4a83aee72c4..908398da629f7 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 52623 | 243 | 39535 | 1930 | +| 52632 | 243 | 39544 | 1932 | ## Plugin Directory @@ -179,7 +179,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | AI Assistant for Search | 6 | 0 | 6 | 0 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | Plugin hosting shared features for connectors | 19 | 0 | 19 | 3 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 18 | 0 | 10 | 0 | -| | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 6 | 0 | 6 | 0 | +| | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 10 | 0 | 10 | 0 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 10 | 0 | 6 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | Plugin to provide access to and rendering of python notebooks for use in the persistent developer console. | 10 | 0 | 10 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 17 | 0 | 11 | 1 | @@ -256,8 +256,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 1 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 18 | 0 | 18 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 4 | 0 | 4 | 0 | -| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 51 | 0 | 51 | 9 | -| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 201 | 0 | 201 | 31 | +| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 53 | 0 | 53 | 9 | +| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 204 | 0 | 204 | 33 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 316 | 0 | 315 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 11 | 0 | 11 | 0 | | | [@elastic/security-defend-workflows](https://github.com/orgs/elastic/teams/security-defend-workflows) | - | 3 | 0 | 3 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index bf8db010244dd..26d7c9c969ddc 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index b735fab07dea8..923fe76dbc464 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index d827e2f3ba307..c30d5f49f61ce 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index bc572f33aeff0..5e0fc31881f4b 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 089b5112d82f8..e3aecf65ea502 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index a11ece5005d6b..719d6340a68cc 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 441862abda06f..093bf4409da7f 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 1c5176148649e..8558cf0f6e0aa 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 13f0ac25761d1..524d0519041a4 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 4b6ca8bbe2830..55ffba4f93e71 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index e7345c0a8a77e..7835452fc8e1b 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index c1cd7d3112d6e..66a83f84b9ae8 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 5770257a629ad..da2d0665bab32 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 7e62d28302d0c..ce9d137330667 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 52376ab3f05e7..6493c183bf1d7 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 252c74c791db6..7c9f3dac7cf17 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 8a7ed9e4a6e0d..de3a94a7d7cd9 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_assistant.mdx b/api_docs/search_assistant.mdx index 1f8c4117c588f..91e578291858c 100644 --- a/api_docs/search_assistant.mdx +++ b/api_docs/search_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchAssistant title: "searchAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the searchAssistant plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchAssistant'] --- import searchAssistantObj from './search_assistant.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index a4cdce03e3494..e906c5523870a 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_homepage.mdx b/api_docs/search_homepage.mdx index 521708d8d58ad..d14cd8e67279f 100644 --- a/api_docs/search_homepage.mdx +++ b/api_docs/search_homepage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchHomepage title: "searchHomepage" image: https://source.unsplash.com/400x175/?github description: API docs for the searchHomepage plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchHomepage'] --- import searchHomepageObj from './search_homepage.devdocs.json'; diff --git a/api_docs/search_indices.devdocs.json b/api_docs/search_indices.devdocs.json index 67e3485ffdae5..e79f47a7894f0 100644 --- a/api_docs/search_indices.devdocs.json +++ b/api_docs/search_indices.devdocs.json @@ -75,7 +75,64 @@ "common": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "searchIndices", + "id": "def-common.IndicesStatusResponse", + "type": "Interface", + "tags": [], + "label": "IndicesStatusResponse", + "description": [], + "path": "x-pack/plugins/search_indices/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "searchIndices", + "id": "def-common.IndicesStatusResponse.indexNames", + "type": "Array", + "tags": [], + "label": "indexNames", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/search_indices/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "searchIndices", + "id": "def-common.UserStartPrivilegesResponse", + "type": "Interface", + "tags": [], + "label": "UserStartPrivilegesResponse", + "description": [], + "path": "x-pack/plugins/search_indices/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "searchIndices", + "id": "def-common.UserStartPrivilegesResponse.privileges", + "type": "Object", + "tags": [], + "label": "privileges", + "description": [], + "signature": [ + "{ canCreateApiKeys: boolean; canCreateIndex: boolean; }" + ], + "path": "x-pack/plugins/search_indices/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ { diff --git a/api_docs/search_indices.mdx b/api_docs/search_indices.mdx index 3613604cef5e8..1812f60b5c8b9 100644 --- a/api_docs/search_indices.mdx +++ b/api_docs/search_indices.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchIndices title: "searchIndices" image: https://source.unsplash.com/400x175/?github description: API docs for the searchIndices plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchIndices'] --- import searchIndicesObj from './search_indices.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-ki | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 6 | 0 | 6 | 0 | +| 10 | 0 | 10 | 0 | ## Client @@ -41,6 +41,9 @@ Contact [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-ki ## Common +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index 0ade59a300892..f2ace37c453c9 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index 531903ed35548..96eeb74884b60 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index 477889334c91b..831135e7c8899 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 8deba975fe079..e289d2ade1afa 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index d8012610139a2..ae4e037e5e71d 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -3324,7 +3324,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: true; readonly responseActionsSentinelOneKillProcessEnabled: true; readonly responseActionsSentinelOneProcessesEnabled: true; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: true; readonly responseActionScanEnabled: true; readonly securitySolutionNotesEnabled: false; readonly entityAlertPreviewDisabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly assistantBedrockChat: true; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: true; readonly jamfDataInAnalyzerEnabled: false; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineDisabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly prebuiltRulesCustomizationEnabled: false; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: true; readonly valueListItemsModalEnabled: true; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: true; readonly dataIngestionHubEnabled: false; }" + "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: true; readonly responseActionsSentinelOneKillProcessEnabled: true; readonly responseActionsSentinelOneProcessesEnabled: true; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: true; readonly responseActionScanEnabled: true; readonly securitySolutionNotesEnabled: false; readonly entityAlertPreviewDisabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly assistantBedrockChat: true; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: true; readonly jamfDataInAnalyzerEnabled: true; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineDisabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly prebuiltRulesCustomizationEnabled: false; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: true; readonly valueListItemsModalEnabled: true; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: true; readonly dataIngestionHubEnabled: false; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 41a096719814c..77b452878fa70 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 1431fc2b99689..3d9049b43d2c2 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 63b9bbb464076..7f401033ab837 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 68be69da0a1b3..3a66ca3ae8c1b 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index 347746f6e3ee4..7507c218b3ad9 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index 1678e4aafd73d..25f8e60fcd4bf 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 9b6b2293583fa..81fa8b0bd5ccd 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index fea6b8d2ce886..8840b6fe9b7cf 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 35da9ebb35b26..44d6d76eec612 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 0c0d77b44e2f4..7866c061cf7be 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 0f43496f3acbe..07eff2e32f515 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 871e9b98b71b9..b8475bcdf867f 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 192e01f97ea8a..82ebcf572b38c 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 123048e006f42..9975a683c2fc6 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index c8949f5e34bbe..0092af0da949f 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 23e0f6d9173d8..50b7b81a75760 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 51a9b1225e665..08d7f118d0da8 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 60a805a1a5424..750e14de23137 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 4003e8e1eaa57..ace667e6e035d 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 81a6991867202..7d2ca3e44137f 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 233ee6fcd4dce..4182ee2d921a7 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 838efe436b1fb..dd0573a7dad31 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 56345dd4fd85d..147415a02455d 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 87c020de36ede..bc047abd77f93 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index b8ed0c64d461d..6e9dc36957bab 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 7ab87b7231a77..28ebf3b09f032 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 706d6f498b8ee..71c9f28b32724 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index f68ea3b3dd30b..47c6345975227 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index d20397da5b285..ddddde515e257 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index b6509075c17ca..fe41ec1fa440d 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 7717d2ab968cc..1986d4cc93a16 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index fbe0ec116dd60..52db8bff35a05 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index c7fe38fcf7e4e..9bc6e6e6365ad 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 59a5e855c3912..7b5e9d38452bd 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index dc91080a3f1fb..0922ed4326778 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 5c051c958d82e..ff203dbd3293b 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index ca60a94387e0e..99d6c80770730 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index acc7787eabc8a..1e4c96030615c 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index c6ac72815cff6..8400a667f3f2f 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 1e4d3c5cfa72e..b00f3eb7627c8 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index eeb603be9ddb1..a1abd27f4405a 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 3918ad3f1449c..23bbfa5922da0 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index ae46b6c7569c7..4e0c973ce0fb9 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2024-08-26 +date: 2024-08-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 6d3721a493039b8caa83d381b171e1111210d463 Mon Sep 17 00:00:00 2001 From: Rickyanto Ang Date: Tue, 27 Aug 2024 00:43:16 -0700 Subject: [PATCH 19/38] [Cloud Security] Misconfiguration preview & Refactor CSP Plugin to include new package PHASE 2 (#190933) ## Summary The previous https://github.com/elastic/kibana/pull/190105 was way too big and made it hard to review without missing any bugs or potential bugs, Thus we decided we are going to make series of smaller PR to make things more manageable We will be splitting it into 4 PR Phase 1: Creating empty packages for csp and csp-common Phase 2: Move Types from CSP plugin to the Package + Deleting duplicates in the CSP plugin where possible Phase 3: Move Functions, Utils or Helpers, Hooks to Package Phase 4: Misconfiguration Preview feature (with Cypress test and other required test) This is **Phase 2** of the Process --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../constants.ts | 20 +++++++ .../index.ts | 22 ++++++++ .../schema/index.ts | 8 +++ .../schema/rules.ts | 48 +++++++++++++++++ .../tsconfig.json | 20 +++++++ .../types.ts} | 42 +++++++++++++-- .../kbn-cloud-security-posture/index.ts | 8 +++ .../kbn-cloud-security-posture/tsconfig.json | 37 +++++++++++++ .../kbn-cloud-security-posture/type.ts | 53 +++++++++++++++++++ .../common/constants.ts | 16 +----- .../common/schemas/stats.ts | 2 +- .../common/types/index.ts | 2 - .../common/types/rules/v3.ts | 31 +---------- .../common/types/rules/v4.ts | 22 ++------ .../common/types/rules/v5.ts | 9 +--- .../common/types_old.ts | 42 +-------------- .../common/utils/detection_rules.test.ts | 2 +- .../common/utils/detection_rules.ts | 2 +- .../common/utils/helpers.ts | 2 +- .../common/utils/rules_states.ts | 2 +- .../public/common/api/use_data_view.ts | 2 +- .../public/common/api/use_setup_status_api.ts | 4 +- .../public/common/api/use_stats_api.ts | 7 +-- .../public/common/constants.ts | 4 +- .../hooks/use_benchmark_dynamic_values.ts | 2 +- .../public/common/hooks/use_kibana.ts | 2 +- .../public/common/navigation/constants.ts | 2 +- .../public/common/types.ts | 8 +-- .../cloud_security_data_table.tsx | 2 +- .../fleet_extensions/policy_template_form.tsx | 2 +- .../policy_template_selectors.tsx | 8 +-- .../components/fleet_extensions/utils.ts | 3 +- .../no_findings_states/no_findings_states.tsx | 5 +- .../components/no_vulnerabilities_states.tsx | 2 +- .../compliance_dashboard.test.tsx | 7 +-- .../compliance_dashboard.tsx | 9 ++-- .../benchmarks_section.test.tsx | 2 +- .../summary_section.test.tsx | 2 +- .../dashboard_sections/summary_section.tsx | 8 +-- .../configurations/__mocks__/findings.ts | 2 +- .../configurations.handlers.mock.ts | 2 +- .../configurations/configurations.test.tsx | 2 +- .../findings_detection_rule_counter.tsx | 2 +- .../findings_flyout/findings_flyout.test.tsx | 2 +- .../findings_flyout/findings_flyout.tsx | 2 +- .../findings_flyout/json_tab.tsx | 2 +- .../findings_flyout/overview_tab.tsx | 4 +- .../findings_flyout/rule_tab.tsx | 2 +- .../findings_flyout/table_tab.tsx | 2 +- .../latest_findings/latest_findings_table.tsx | 2 +- .../use_get_benchmark_rules_state_api.ts | 4 +- .../latest_findings/use_grouped_findings.tsx | 2 +- .../latest_findings/use_latest_findings.ts | 13 +++-- .../use_latest_findings_grouping.tsx | 2 +- .../layout/findings_search_bar.tsx | 2 +- .../create_detection_rule_from_benchmark.ts | 7 ++- .../public/pages/rules/rules_flyout.tsx | 2 +- .../public/pages/rules/use_csp_rules_state.ts | 4 +- .../hooks/use_latest_vulnerabilities.tsx | 5 +- .../cloud_security_posture/public/plugin.tsx | 8 +-- .../handlers/dataview.handlers.mock.ts | 6 +-- .../public/test/mock_server/mock_server.ts | 2 +- .../mock_server/mock_server_test_provider.tsx | 2 +- .../public/test/test_provider.tsx | 2 +- .../cloud_security_posture/public/types.ts | 46 ++-------------- .../server/create_indices/latest_indices.ts | 2 +- .../latest_findings_transform.ts | 2 +- .../server/lib/check_index_status.ts | 3 +- .../server/lib/fleet_util.ts | 3 +- .../cloud_accounts_stats_collector.ts | 3 +- .../server/lib/telemetry/collectors/types.ts | 2 +- .../benchmark_rules/bulk_action/utils.ts | 2 +- .../benchmark_rules/get_states/get_states.ts | 4 +- .../routes/benchmark_rules/get_states/v1.ts | 3 +- .../compliance_dashboard/get_clusters.ts | 2 +- .../server/routes/status/status.test.ts | 3 +- .../server/routes/status/status.ts | 24 +++++---- .../server/saved_objects/data_views.ts | 2 +- .../cloud_security_posture/server/types.ts | 2 +- .../cloud_security_posture/tsconfig.json | 5 +- .../server/cloud_security/constants.ts | 4 +- .../tsconfig.json | 1 + .../apis/cloud_security_posture/helper.ts | 2 +- .../status/status_index_timeout.ts | 2 +- .../status/status_indexed.ts | 2 +- .../status/status_indexing.ts | 2 +- .../status_not_deployed_not_installed.ts | 2 +- .../status/status_unprivileged.ts | 2 +- .../status/status_waiting_for_results.ts | 2 +- .../routes/helper/user_roles_utilites.ts | 2 +- x-pack/test/tsconfig.json | 3 +- .../status/status_indexed.ts | 2 +- .../status/status_indexing.ts | 2 +- .../status_not_deployed_not_installed.ts | 2 +- x-pack/test_serverless/tsconfig.json | 1 + 95 files changed, 392 insertions(+), 303 deletions(-) create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/constants.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/index.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json rename x-pack/{plugins/cloud_security_posture/common/schemas/csp_finding.ts => packages/kbn-cloud-security-posture-common/types.ts} (54%) create mode 100644 x-pack/packages/kbn-cloud-security-posture/index.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture/tsconfig.json create mode 100644 x-pack/packages/kbn-cloud-security-posture/type.ts diff --git a/x-pack/packages/kbn-cloud-security-posture-common/constants.ts b/x-pack/packages/kbn-cloud-security-posture-common/constants.ts new file mode 100644 index 0000000000000..935e747b20fa8 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/constants.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export const KSPM_POLICY_TEMPLATE = 'kspm'; +export const CSPM_POLICY_TEMPLATE = 'cspm'; +export const CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN = + 'logs-cloud_security_posture.findings_latest-default'; +export const CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN = + 'logs-*_latest_misconfigurations_cdr'; +export const CDR_MISCONFIGURATIONS_INDEX_PATTERN = `${CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN},${CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN}`; +export const LATEST_FINDINGS_RETENTION_POLICY = '26h'; +export const MAX_FINDINGS_TO_LOAD = 500; +export const CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH = + '/internal/cloud_security_posture/rules/_get_states'; +export const CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION = '1'; +export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; +export const STATUS_API_CURRENT_VERSION = '1'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/index.ts b/x-pack/packages/kbn-cloud-security-posture-common/index.ts new file mode 100644 index 0000000000000..f4d7ac2e34dd9 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/index.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +// Careful of exporting anything from this file as any file(s) you export here will cause your page bundle size to increase. +// If you're using functions/types/etc... internally or within integration tests it's best to import directly from their paths +// than expose the functions/types/etc... here. You should _only_ expose functions/types/etc... that need to be shared with other plugins here. + +export type { + CspStatusCode, + IndexStatus, + IndexDetails, + BaseCspSetupBothPolicy, + BaseCspSetupStatus, + CspSetupStatus, + CspFinding, +} from './types'; +export * from './constants'; +export type { CspBenchmarkRuleMetadata, CspBenchmarkRulesStates } from './schema/rules'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts new file mode 100644 index 0000000000000..981633d2a3fad --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/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 { ruleStateAttributes, cspBenchmarkRuleMetadataSchema, rulesStates } from './rules'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts new file mode 100644 index 0000000000000..67bb37e4e1702 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { TypeOf, schema } from '@kbn/config-schema'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../constants'; + +export type CspBenchmarkRuleMetadata = TypeOf; + +export const cspBenchmarkRuleMetadataSchema = schema.object({ + audit: schema.string(), + benchmark: schema.object({ + name: schema.string(), + posture_type: schema.maybe( + schema.oneOf([schema.literal(CSPM_POLICY_TEMPLATE), schema.literal(KSPM_POLICY_TEMPLATE)]) + ), + id: schema.string(), + version: schema.string(), + rule_number: schema.maybe(schema.string()), + }), + default_value: schema.maybe(schema.string()), + description: schema.string(), + id: schema.string(), + impact: schema.maybe(schema.string()), + name: schema.string(), + profile_applicability: schema.string(), + rationale: schema.string(), + references: schema.maybe(schema.string()), + rego_rule_id: schema.string(), + remediation: schema.string(), + section: schema.string(), + tags: schema.arrayOf(schema.string()), + version: schema.string(), +}); + +export const ruleStateAttributes = schema.object({ + muted: schema.boolean(), + benchmark_id: schema.string(), + benchmark_version: schema.string(), + rule_number: schema.string(), + rule_id: schema.string(), +}); + +export const rulesStates = schema.recordOf(schema.string(), ruleStateAttributes); + +export type CspBenchmarkRulesStates = TypeOf; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json new file mode 100644 index 0000000000000..1eb47d23c1542 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/config-schema", + ] +} diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts b/x-pack/packages/kbn-cloud-security-posture-common/types.ts similarity index 54% rename from x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts rename to x-pack/packages/kbn-cloud-security-posture-common/types.ts index 7ac4e79393f01..7a9d5fee09c8f 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/types.ts @@ -4,10 +4,46 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -// TODO: this needs to be defined in a versioned schema import type { EcsDataStream, EcsEvent } from '@elastic/ecs'; -import { CspBenchmarkRuleMetadata } from '../types/latest'; +import type { CspBenchmarkRuleMetadata } from './schema/rules'; + +export type CspStatusCode = + | 'indexed' // latest findings index exists and has results + | 'indexing' // index timeout was not surpassed since installation, assumes data is being indexed + | 'unprivileged' // user lacks privileges for the latest findings index + | 'index-timeout' // index timeout was surpassed since installation + | 'not-deployed' // no healthy agents were deployed + | 'not-installed' // number of installed csp integrations is 0; + | 'waiting_for_results'; // have healthy agents but no findings at all, assumes data is being indexed for the 1st time + +export type IndexStatus = + | 'not-empty' // Index contains documents + | 'empty' // Index doesn't contain documents (or doesn't exist) + | 'unprivileged'; // User doesn't have access to query the index + +export interface IndexDetails { + index: string; + status: IndexStatus; +} + +export interface BaseCspSetupBothPolicy { + status: CspStatusCode; + installedPackagePolicies: number; + healthyAgents: number; +} + +export interface BaseCspSetupStatus { + indicesDetails: IndexDetails[]; + latestPackageVersion: string; + cspm: BaseCspSetupBothPolicy; + kspm: BaseCspSetupBothPolicy; + vuln_mgmt: BaseCspSetupBothPolicy; + isPluginInitialized: boolean; + installedPackageVersion?: string | undefined; + hasMisconfigurationsFindings?: boolean; +} + +export type CspSetupStatus = BaseCspSetupStatus; export interface CspFinding { '@timestamp': string; diff --git a/x-pack/packages/kbn-cloud-security-posture/index.ts b/x-pack/packages/kbn-cloud-security-posture/index.ts new file mode 100644 index 0000000000000..a0e4ba8dbc1b2 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture/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 * from './type'; diff --git a/x-pack/packages/kbn-cloud-security-posture/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture/tsconfig.json new file mode 100644 index 0000000000000..a2652215c4e79 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture/tsconfig.json @@ -0,0 +1,37 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/licensing-plugin", + "@kbn/data-views-plugin", + "@kbn/unified-search-plugin", + "@kbn/ui-actions-plugin", + "@kbn/field-formats-plugin", + "@kbn/data-view-field-editor-plugin", + "@kbn/data-plugin", + "@kbn/kibana-utils-plugin", + "@kbn/charts-plugin", + "@kbn/discover-plugin", + "@kbn/fleet-plugin", + "@kbn/usage-collection-plugin", + "@kbn/share-plugin", + "@kbn/es-query", + "@kbn/cloud-plugin", + "@kbn/spaces-plugin", + ] +} diff --git a/x-pack/packages/kbn-cloud-security-posture/type.ts b/x-pack/packages/kbn-cloud-security-posture/type.ts new file mode 100644 index 0000000000000..70daabecf67d3 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture/type.ts @@ -0,0 +1,53 @@ +/* + * 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 type { CloudSetup } from '@kbn/cloud-plugin/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; +import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { ToastsStart } from '@kbn/core/public'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; + +import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import type { DiscoverStart } from '@kbn/discover-plugin/public'; +import type { FleetStart } from '@kbn/fleet-plugin/public'; +import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import { SharePluginStart } from '@kbn/share-plugin/public'; +import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; + +import type { BoolQuery } from '@kbn/es-query'; +export interface FindingsBaseEsQuery { + query?: { + bool: BoolQuery; + }; +} + +export interface CspClientPluginStartDeps { + // required + data: DataPublicPluginStart; + dataViews: DataViewsServicePublic; + dataViewFieldEditor: IndexPatternFieldEditorStart; + unifiedSearch: UnifiedSearchPublicPluginStart; + uiActions: UiActionsStart; + fieldFormats: FieldFormatsStart; + toastNotifications: ToastsStart; + charts: ChartsPluginStart; + discover: DiscoverStart; + fleet: FleetStart; + licensing: LicensingPluginStart; + share: SharePluginStart; + storage: Storage; + spaces: SpacesPluginStart; + cloud: CloudSetup; + + // optional + usageCollection?: UsageCollectionStart; +} diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index 720251dee5a77..b35780c438403 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { KSPM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { AwsCredentialsTypeFieldMap, GcpCredentialsTypeFieldMap, @@ -13,8 +14,6 @@ import { } from './types_old'; export const CLOUD_SECURITY_INTERTAL_PREFIX_ROUTE_PATH = '/internal/cloud_security_posture/'; -export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; -export const STATUS_API_CURRENT_VERSION = '1'; export const STATS_ROUTE_PATH = '/internal/cloud_security_posture/stats/{policy_template}'; @@ -31,10 +30,6 @@ export const CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH = '/internal/cloud_security_posture/rules/_bulk_action'; export const CSP_BENCHMARK_RULES_BULK_ACTION_API_CURRENT_VERSION = '1'; -export const CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH = - '/internal/cloud_security_posture/rules/_get_states'; -export const CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION = '1'; - export const GET_DETECTION_RULE_ALERTS_STATUS_PATH = '/internal/cloud_security_posture/detection_engine_rules/alerts/_status'; export const DETECTION_RULE_ALERTS_STATUS_API_CURRENT_VERSION = '1'; @@ -45,11 +40,6 @@ export const CLOUD_SECURITY_POSTURE_PACKAGE_NAME = 'cloud_security_posture'; export const CDR_MISCONFIGURATIONS_DATA_VIEW_NAME = 'Latest Cloud Security Misconfigurations'; export const CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX = 'security_solution_cdr_latest_misconfigurations'; -export const CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN = - 'logs-cloud_security_posture.findings_latest-default'; -export const CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN = - 'logs-*_latest_misconfigurations_cdr'; -export const CDR_MISCONFIGURATIONS_INDEX_PATTERN = `${CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN},${CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN}`; export const CDR_VULNERABILITIES_DATA_VIEW_NAME = 'Latest Cloud Security Vulnerabilities'; export const CDR_VULNERABILITIES_DATA_VIEW_ID_PREFIX = @@ -65,8 +55,6 @@ export const LATEST_FINDINGS_INDEX_TEMPLATE_NAME = 'logs-cloud_security_posture. export const LATEST_FINDINGS_INDEX_DEFAULT_NS = 'logs-cloud_security_posture.findings_latest-default'; -export const LATEST_FINDINGS_RETENTION_POLICY = '26h'; - export const BENCHMARK_SCORE_INDEX_TEMPLATE_NAME = 'logs-cloud_security_posture.scores'; export const BENCHMARK_SCORE_INDEX_PATTERN = 'logs-cloud_security_posture.scores-*'; export const BENCHMARK_SCORE_INDEX_DEFAULT_NS = 'logs-cloud_security_posture.scores-default'; @@ -127,8 +115,6 @@ export const CIS_GCP = 'cis_gcp'; export const CIS_K8S = 'cis_k8s'; export const CIS_EKS = 'cis_eks'; export const CIS_AZURE = 'cis_azure'; -export const KSPM_POLICY_TEMPLATE = 'kspm'; -export const CSPM_POLICY_TEMPLATE = 'cspm'; export const VULN_MGMT_POLICY_TEMPLATE = 'vuln_mgmt'; export const CNVM_POLICY_TEMPLATE = 'cnvm'; export const SUPPORTED_POLICY_TEMPLATES = [ diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/stats.ts b/x-pack/plugins/cloud_security_posture/common/schemas/stats.ts index e8b3657996e0f..3b2fa14c06b30 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/stats.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/stats.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../constants'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; // this pages follows versioning interface strategy https://docs.elastic.dev/kibana-dev-docs/versioning-interfaces diff --git a/x-pack/plugins/cloud_security_posture/common/types/index.ts b/x-pack/plugins/cloud_security_posture/common/types/index.ts index 04fa2a95a8d5e..c59071d114251 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/index.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/index.ts @@ -16,8 +16,6 @@ export * as benchmarkV2 from './benchmarks/v2'; // Explicit export of everything from latest export type { - cspBenchmarkRuleMetadataSchema, - CspBenchmarkRuleMetadata, CspBenchmarkRule, FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts index a00bf1a8077e6..7c0a536de79a5 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts @@ -6,7 +6,8 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../constants'; + +import { cspBenchmarkRuleMetadataSchema } from '@kbn/cloud-security-posture-common/schema'; export const DEFAULT_BENCHMARK_RULES_PER_PAGE = 25; @@ -14,36 +15,8 @@ export const DEFAULT_BENCHMARK_RULES_PER_PAGE = 25; export type FindCspBenchmarkRuleRequest = TypeOf; -export type CspBenchmarkRuleMetadata = TypeOf; - export type CspBenchmarkRule = TypeOf; -export const cspBenchmarkRuleMetadataSchema = schema.object({ - audit: schema.string(), - benchmark: schema.object({ - name: schema.string(), - posture_type: schema.maybe( - schema.oneOf([schema.literal(CSPM_POLICY_TEMPLATE), schema.literal(KSPM_POLICY_TEMPLATE)]) - ), - id: schema.string(), - version: schema.string(), - rule_number: schema.maybe(schema.string()), - }), - default_value: schema.maybe(schema.string()), - description: schema.string(), - id: schema.string(), - impact: schema.maybe(schema.string()), - name: schema.string(), - profile_applicability: schema.string(), - rationale: schema.string(), - references: schema.maybe(schema.string()), - rego_rule_id: schema.string(), - remediation: schema.string(), - section: schema.string(), - tags: schema.arrayOf(schema.string()), - version: schema.string(), -}); - export const cspBenchmarkRuleSchema = schema.object({ metadata: cspBenchmarkRuleMetadataSchema, }); diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts index 33134eed32e38..231fb4c65a9bb 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts @@ -6,15 +6,11 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; +import { ruleStateAttributes, rulesStates } from '@kbn/cloud-security-posture-common/schema'; import { BenchmarksCisId } from '../latest'; import { DEFAULT_BENCHMARK_RULES_PER_PAGE } from './v3'; -export type { - cspBenchmarkRuleMetadataSchema, - CspBenchmarkRuleMetadata, - cspBenchmarkRuleSchema, - CspBenchmarkRule, - FindCspBenchmarkRuleResponse, -} from './v3'; +export type { cspBenchmarkRuleSchema, CspBenchmarkRule, FindCspBenchmarkRuleResponse } from './v3'; export type FindCspBenchmarkRuleRequest = TypeOf; @@ -26,8 +22,6 @@ export type CspBenchmarkRulesBulkActionRequestSchema = TypeOf< export type RuleStateAttributes = TypeOf; -export type CspBenchmarkRulesStates = TypeOf; - export type CspSettings = TypeOf; export const findCspBenchmarkRuleRequestSchema = schema.object({ @@ -143,16 +137,6 @@ export interface CspBenchmarkRulesBulkActionResponse { message: string; } -const ruleStateAttributes = schema.object({ - muted: schema.boolean(), - benchmark_id: schema.string(), - benchmark_version: schema.string(), - rule_number: schema.string(), - rule_id: schema.string(), -}); - -const rulesStates = schema.recordOf(schema.string(), ruleStateAttributes); - export const cspSettingsSchema = schema.object({ rules: rulesStates, }); diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts index 6f30ed446531a..1d70528d457ea 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts @@ -7,20 +7,13 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { DEFAULT_BENCHMARK_RULES_PER_PAGE } from './v3'; -export type { - cspBenchmarkRuleMetadataSchema, - CspBenchmarkRuleMetadata, - cspBenchmarkRuleSchema, - CspBenchmarkRule, - FindCspBenchmarkRuleResponse, -} from './v3'; +export type { cspBenchmarkRuleSchema, CspBenchmarkRule, FindCspBenchmarkRuleResponse } from './v3'; export type { PageUrlParams, rulesToUpdate, CspBenchmarkRulesBulkActionRequestSchema, CspBenchmarkRulesBulkActionResponse, RuleStateAttributes, - CspBenchmarkRulesStates, cspSettingsSchema, CspSettings, BulkActionBenchmarkRulesResponse, diff --git a/x-pack/plugins/cloud_security_posture/common/types_old.ts b/x-pack/plugins/cloud_security_posture/common/types_old.ts index 19e18902b7ea1..b5e399e4e639c 100644 --- a/x-pack/plugins/cloud_security_posture/common/types_old.ts +++ b/x-pack/plugins/cloud_security_posture/common/types_old.ts @@ -5,11 +5,11 @@ * 2.0. */ import { type TypeOf } from '@kbn/config-schema'; -import { CspFinding } from './schemas/csp_finding'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES } from './constants'; import { getComplianceDashboardSchema } from './schemas/stats'; -import type { CspBenchmarkRuleMetadata } from './types/latest'; export type AwsCredentialsType = | 'assume_role' @@ -100,44 +100,6 @@ export interface ComplianceDashboardDataV2 { benchmarks: BenchmarkData[]; } -export type CspStatusCode = - | 'indexed' // latest findings index exists and has results - | 'indexing' // index timeout was not surpassed since installation, assumes data is being indexed - | 'unprivileged' // user lacks privileges for the latest findings index - | 'index-timeout' // index timeout was surpassed since installation - | 'not-deployed' // no healthy agents were deployed - | 'not-installed' // number of installed csp integrations is 0; - | 'waiting_for_results'; // have healthy agents but no findings at all, assumes data is being indexed for the 1st time - -export type IndexStatus = - | 'not-empty' // Index contains documents - | 'empty' // Index doesn't contain documents (or doesn't exist) - | 'unprivileged'; // User doesn't have access to query the index - -export interface IndexDetails { - index: string; - status: IndexStatus; -} - -export interface BaseCspSetupBothPolicy { - status: CspStatusCode; - installedPackagePolicies: number; - healthyAgents: number; -} - -export interface BaseCspSetupStatus { - indicesDetails: IndexDetails[]; - latestPackageVersion: string; - cspm: BaseCspSetupBothPolicy; - kspm: BaseCspSetupBothPolicy; - vuln_mgmt: BaseCspSetupBothPolicy; - isPluginInitialized: boolean; - installedPackageVersion?: string | undefined; - hasMisconfigurationsFindings?: boolean; -} - -export type CspSetupStatus = BaseCspSetupStatus; - export type BenchmarkId = CspBenchmarkRuleMetadata['benchmark']['id']; export type BenchmarkName = CspBenchmarkRuleMetadata['benchmark']['name']; export type RuleSection = CspBenchmarkRuleMetadata['section']; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts index a067ef4e1871a..fa514fe0fc2a5 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CspBenchmarkRuleMetadata } from '../types'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; import { convertRuleTagsToMatchAllKQL, convertRuleTagsToMatchAnyKQL, diff --git a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts index 61567211c8d22..4ae8385290955 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CspBenchmarkRuleMetadata } from '../types/latest'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; const CSP_RULE_TAG = 'Cloud Security'; const CSP_RULE_TAG_USE_CASE = 'Use Case: Configuration Audit'; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 6222b457e7ad6..950803c2c65c9 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -6,6 +6,7 @@ */ import { Truthy } from 'lodash'; +import type { BaseCspSetupStatus } from '@kbn/cloud-security-posture-common'; import { NewPackagePolicy, NewPackagePolicyInput, @@ -25,7 +26,6 @@ import { import type { BenchmarkId, Score, - BaseCspSetupStatus, AwsCredentialsType, GcpCredentialsType, AzureCredentialsType, diff --git a/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts b/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts index a343c91af91f9..9a142729e410b 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts @@ -5,7 +5,7 @@ * 2.0. */ import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types'; -import { CspBenchmarkRulesStates } from '../types/latest'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; export const buildMutedRulesFilter = ( rulesStates: CspBenchmarkRulesStates diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_data_view.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_data_view.ts index 41b40da90a6d4..304230498d4f4 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_data_view.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_data_view.ts @@ -8,7 +8,7 @@ import { useQuery } from '@tanstack/react-query'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; -import { CspClientPluginStartDeps } from '../../types'; +import { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; /** * Hook to retrieve a Data View by it's Index Pattern title diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts index 35f49282a475e..003f841772285 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts @@ -6,9 +6,9 @@ */ import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; +import { STATUS_API_CURRENT_VERSION, STATUS_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../hooks/use_kibana'; -import { type CspSetupStatus } from '../../../common/types_old'; -import { STATUS_API_CURRENT_VERSION, STATUS_ROUTE_PATH } from '../../../common/constants'; const getCspSetupStatusQueryKey = 'csp_status_key'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts index e973633210d9c..77497d16cd76c 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts @@ -6,13 +6,10 @@ */ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../hooks/use_kibana'; import { ComplianceDashboardDataV2, PosturePolicyTemplate } from '../../../common/types_old'; -import { - CSPM_POLICY_TEMPLATE, - KSPM_POLICY_TEMPLATE, - STATS_ROUTE_PATH, -} from '../../../common/constants'; +import { STATS_ROUTE_PATH } from '../../../common/constants'; // TODO: consolidate both hooks into one hook with a dynamic key export const CSPM_STATS_QUERY_KEY = ['csp_cspm_dashboard_stats']; diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 8054917ba7462..8eb996dd15643 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { CloudSecurityPolicyTemplate, PostureInput } from '../../common/types_old'; import { CLOUDBEAT_EKS, @@ -15,8 +16,6 @@ import { CLOUDBEAT_GCP, CLOUDBEAT_AZURE, CLOUDBEAT_VULN_MGMT_AWS, - KSPM_POLICY_TEMPLATE, - CSPM_POLICY_TEMPLATE, VULN_MGMT_POLICY_TEMPLATE, CLOUDBEAT_VULN_MGMT_GCP, CLOUDBEAT_VULN_MGMT_AZURE, @@ -35,7 +34,6 @@ export const statusColors = { }; export const CSP_MOMENT_FORMAT = 'MMMM D, YYYY @ HH:mm:ss.SSS'; -export const MAX_FINDINGS_TO_LOAD = 500; export const DEFAULT_VISIBLE_ROWS_PER_PAGE = 25; export const LOCAL_STORAGE_DATA_TABLE_PAGE_SIZE_KEY = 'cloudPosture:dataTable:pageSize'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts index 5fe3f8f69050a..7f9a2b5fd35f6 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { useCspIntegrationLink } from '../navigation/use_csp_integration_link'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; import { BenchmarksCisId } from '../../../common/types/benchmarks/v2'; type BenchmarkDynamicNames = diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_kibana.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_kibana.ts index 1c6f252080e11..a392e9213dffc 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_kibana.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_kibana.ts @@ -7,7 +7,7 @@ import type { CoreStart } from '@kbn/core/public'; import { useKibana as useKibanaBase } from '@kbn/kibana-react-plugin/public'; -import type { CspClientPluginStartDeps } from '../../types'; +import type { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; type CspKibanaContext = CoreStart & CspClientPluginStartDeps; diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts index 18b3bf1268e26..055495b59dd11 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { CspBenchmarksPage, CspPage, CspPageNavigationItem } from './types'; const NAV_ITEMS_NAMES = { diff --git a/x-pack/plugins/cloud_security_posture/public/common/types.ts b/x-pack/plugins/cloud_security_posture/public/common/types.ts index d0d491c256e0e..62e0abe677679 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/types.ts @@ -5,7 +5,7 @@ * 2.0. */ import type { Criteria } from '@elastic/eui'; -import type { BoolQuery, Filter, Query, EsQueryConfig } from '@kbn/es-query'; +import type { Filter, Query, EsQueryConfig } from '@kbn/es-query'; export interface FindingsBaseURLQuery { query: Query; @@ -24,12 +24,6 @@ export interface FindingsBaseESQueryConfig { config: EsQueryConfig; } -export interface FindingsBaseEsQuery { - query?: { - bool: BoolQuery; - }; -} - export type Sort = NonNullable['sort']>; interface RuleSeverityMapping { diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_data_table/cloud_security_data_table.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_data_table/cloud_security_data_table.tsx index 7b63673707056..1e81f883c69f3 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_data_table/cloud_security_data_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_data_table/cloud_security_data_table.tsx @@ -27,10 +27,10 @@ import { AddFieldFilterHandler } from '@kbn/unified-field-list'; import { generateFilters } from '@kbn/data-plugin/public'; import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { MAX_FINDINGS_TO_LOAD } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../../common/hooks/use_kibana'; import { CloudPostureDataTableResult } from '../../common/hooks/use_cloud_posture_data_table'; import { EmptyState } from '../empty_state'; -import { MAX_FINDINGS_TO_LOAD } from '../../common/constants'; import { useStyles } from './use_styles'; import { AdditionalControls } from './additional_controls'; import { useDataViewContext } from '../../common/contexts/data_view_context'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx index f70fb3a18f690..f57b5d453d81f 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx @@ -28,6 +28,7 @@ import type { PackagePolicyReplaceDefineStepExtensionComponentProps, } from '@kbn/fleet-plugin/public/types'; import { PackageInfo, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { CSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { useIsSubscriptionStatusValid } from '../../common/hooks/use_is_subscription_status_valid'; @@ -39,7 +40,6 @@ import { CLOUDBEAT_AWS, CLOUDBEAT_VANILLA, CLOUDBEAT_VULN_MGMT_AWS, - CSPM_POLICY_TEMPLATE, SUPPORTED_POLICY_TEMPLATES, } from '../../../common/constants'; import { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx index ee76d40e1dcac..c0c489f935be0 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx @@ -10,12 +10,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { NewPackagePolicy, PackageInfo } from '@kbn/fleet-plugin/common'; import { SetupTechnology } from '@kbn/fleet-plugin/public'; import { PackagePolicyReplaceDefineStepExtensionComponentProps } from '@kbn/fleet-plugin/public/types'; -import { - CSPM_POLICY_TEMPLATE, - KSPM_POLICY_TEMPLATE, - VULN_MGMT_POLICY_TEMPLATE, - CNVM_POLICY_TEMPLATE, -} from '../../../common/constants'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; +import { VULN_MGMT_POLICY_TEMPLATE, CNVM_POLICY_TEMPLATE } from '../../../common/constants'; import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types_old'; import { getPolicyTemplateInputOptions, type NewPackagePolicyPostureInput } from './utils'; import { RadioGroup } from './csp_boxed_radio_group'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index 656c70a0dcbfd..5fc4ab08e414c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -13,6 +13,7 @@ import type { RegistryVarsEntry, } from '@kbn/fleet-plugin/common'; import { SetupTechnology } from '@kbn/fleet-plugin/public'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import merge from 'lodash/merge'; import semverValid from 'semver/functions/valid'; import semverCoerce from 'semver/functions/coerce'; @@ -24,8 +25,6 @@ import { CLOUDBEAT_GCP, CLOUDBEAT_VANILLA, CLOUDBEAT_VULN_MGMT_AWS, - CSPM_POLICY_TEMPLATE, - KSPM_POLICY_TEMPLATE, SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES, VULN_MGMT_POLICY_TEMPLATE, diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx index 97dfce7b84c1e..096c6f0e8aae5 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx @@ -20,7 +20,8 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; +import type { IndexDetails, CspStatusCode } from '@kbn/cloud-security-posture-common'; import { FullSizeCenteredPage } from '../full_size_centered_page'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; import { @@ -30,7 +31,7 @@ import { } from '../test_subjects'; import { CloudPosturePage, PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from '../cloud_posture_page'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; -import type { IndexDetails, PostureTypes, CspStatusCode } from '../../../common/types_old'; +import type { PostureTypes } from '../../../common/types_old'; import noDataIllustration from '../../assets/illustrations/no_data_illustration.svg'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx index a2b1aa1d0d831..a15cf0aacd6fa 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx @@ -21,11 +21,11 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; +import type { IndexDetails } from '@kbn/cloud-security-posture-common'; import { VULN_MGMT_POLICY_TEMPLATE } from '../../common/constants'; import { FullSizeCenteredPage } from './full_size_centered_page'; import { CloudPosturePage } from './cloud_posture_page'; import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import type { IndexDetails } from '../../common/types_old'; import { NO_VULNERABILITIES_STATUS_TEST_SUBJ, CNVM_NOT_INSTALLED_ACTION_SUBJ, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx index 915e135967def..46b0e59612083 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { coreMock } from '@kbn/core/public/mocks'; +import type { BaseCspSetupStatus, CspStatusCode } from '@kbn/cloud-security-posture-common'; import { render, screen } from '@testing-library/react'; import { TestProvider } from '../../test/test_provider'; import { ComplianceDashboard, getDefaultTab } from '.'; @@ -31,11 +32,7 @@ import { KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT, PACKAGE_NOT_INSTALLED_TEST_SUBJECT, } from '../../components/cloud_posture_page'; -import { - BaseCspSetupStatus, - ComplianceDashboardDataV2, - CspStatusCode, -} from '../../../common/types_old'; +import { ComplianceDashboardDataV2 } from '../../../common/types_old'; import { cloudPosturePages } from '../../common/navigation/constants'; import { MemoryRouter } from 'react-router-dom'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index af341d5c04606..1629a000d5e64 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -13,13 +13,11 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { Route, Routes } from '@kbn/shared-ux-router'; import { Redirect, useHistory, useLocation } from 'react-router-dom'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; +import type { BaseCspSetupStatus } from '@kbn/cloud-security-posture-common'; import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; -import type { - PosturePolicyTemplate, - ComplianceDashboardDataV2, - BaseCspSetupStatus, -} from '../../../common/types_old'; +import type { PosturePolicyTemplate, ComplianceDashboardDataV2 } from '../../../common/types_old'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import { CloudPosturePage, @@ -41,7 +39,6 @@ import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; import { SummarySection } from './dashboard_sections/summary_section'; import { BenchmarksSection } from './dashboard_sections/benchmarks_section'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; import { cloudPosturePages, cspIntegrationDocsNavigation } from '../../common/navigation/constants'; import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../../common/constants'; import { encodeQuery } from '../../common/navigation/query_utils'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.test.tsx index 79b644af37795..d9c773522581f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.test.tsx @@ -6,12 +6,12 @@ */ import React from 'react'; +import { KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { BenchmarksSection } from './benchmarks_section'; import { getMockDashboardData, getBenchmarkMockData } from '../mock'; import { TestProvider } from '../../../test/test_provider'; -import { KSPM_POLICY_TEMPLATE } from '../../../../common/constants'; import { DASHBOARD_TABLE_COLUMN_SCORE_TEST_ID, DASHBOARD_TABLE_HEADER_SCORE_TEST_ID, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.test.tsx index 04c8382529593..089bd4def089f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.test.tsx @@ -6,13 +6,13 @@ */ import React from 'react'; +import { KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { render, screen } from '@testing-library/react'; import { expectIdsInDoc } from '../../../test/utils'; import { DASHBOARD_COUNTER_CARDS } from '../test_subjects'; import { SummarySection } from './summary_section'; import { mockDashboardData } from '../mock'; import { TestProvider } from '../../../test/test_provider'; -import { KSPM_POLICY_TEMPLATE } from '../../../../common/constants'; describe('', () => { const renderCloudSummarySection = (alterMockData = {}) => { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx index 64d0a225f20d4..1528239562826 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx @@ -15,6 +15,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { useCspIntegrationLink } from '../../../common/navigation/use_csp_integration_link'; import { DASHBOARD_COUNTER_CARDS, DASHBOARD_SUMMARY_CONTAINER } from '../test_subjects'; import { CspCounterCard, CspCounterCardProps } from '../../../components/csp_counter_card'; @@ -28,12 +29,7 @@ import type { } from '../../../../common/types_old'; import { RisksTable } from '../compliance_charts/risks_table'; import { NavFilter, useNavigateFindings } from '../../../common/hooks/use_navigate_findings'; -import { - CSPM_POLICY_TEMPLATE, - KSPM_POLICY_TEMPLATE, - RULE_FAILED, - RULE_PASSED, -} from '../../../../common/constants'; +import { RULE_FAILED, RULE_PASSED } from '../../../../common/constants'; import { AccountsEvaluatedWidget } from '../../../components/accounts_evaluated_widget'; import { FINDINGS_GROUPING_OPTIONS } from '../../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/__mocks__/findings.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/__mocks__/findings.ts index 4b01603b4c03b..4693459c0985d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/__mocks__/findings.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/__mocks__/findings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; export const mockFindingsHit: CspFinding = { result: { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts index e79f737b11a3c..10e79145cd02e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts @@ -6,7 +6,7 @@ */ import { estypes } from '@elastic/elasticsearch'; -import { CspFinding } from '../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { isArray } from 'lodash'; import { http, HttpResponse } from 'msw'; import { v4 as uuidV4 } from 'uuid'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx index 8b1d54b5a1798..f782d90474a3c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx @@ -17,7 +17,7 @@ import { MemoryRouter } from '@kbn/shared-ux-router'; import { findingsNavigation } from '../../common/navigation/constants'; import userEvent from '@testing-library/user-event'; import { FilterManager } from '@kbn/data-plugin/public'; -import { CspClientPluginStartDeps } from '../../types'; +import { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import * as statusHandlers from '../../../server/routes/status/status.handlers.mock'; import { bsearchFindingsHandler, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx index 0ab35a37c8ee4..7a3ef68a21ad9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx @@ -7,7 +7,7 @@ import type { HttpSetup } from '@kbn/core/public'; import React from 'react'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { DetectionRuleCounter } from '../../../components/detection_rule_counter'; import { getFindingsDetectionRuleSearchTags } from '../../../../common/utils/detection_rules'; import { createDetectionRuleFromBenchmarkRule } from '../utils/create_detection_rule_from_benchmark'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.test.tsx index 118ebb86e0d64..a2fbc66188acd 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.test.tsx @@ -5,11 +5,11 @@ * 2.0. */ import React from 'react'; +import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import userEvent from '@testing-library/user-event'; import { FindingsRuleFlyout } from './findings_flyout'; import { render, screen } from '@testing-library/react'; import { TestProvider } from '../../../test/test_provider'; -import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '../../../../common/constants'; import { mockFindingsHit, mockWizFinding } from '../__mocks__/findings'; const onPaginate = jest.fn(); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx index 4d8c5b6569efd..e1086f81367a3 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx @@ -35,11 +35,11 @@ import type { HttpSetup } from '@kbn/core/public'; import { generatePath } from 'react-router-dom'; import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { CSP_DATASET, getDatasetDisplayName } from '../../../common/utils/get_dataset_display_name'; import { truthy } from '../../../../common/utils/helpers'; import { benchmarksNavigation } from '../../../common/navigation/constants'; import cisLogoIcon from '../../../assets/icons/cis_logo.svg'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; import { CspEvaluationBadge } from '../../../components/csp_evaluation_badge'; import { TakeAction } from '../../../components/take_action'; import { TableTab } from './table_tab'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/json_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/json_tab.tsx index 30f8237de91b0..712ea0399cf1d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/json_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/json_tab.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { CodeEditor } from '@kbn/code-editor'; import { XJsonLang } from '@kbn/monaco'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; export const JsonTab = ({ data }: { data: CspFinding }) => (
diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/overview_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/overview_tab.tsx index 38c526df1e758..d25d6d63d213f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/overview_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/overview_tab.tsx @@ -18,19 +18,19 @@ import React, { useMemo } from 'react'; import moment from 'moment'; import type { EuiDescriptionListProps, EuiAccordionProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import { FormattedMessage } from '@kbn/i18n-react'; import { isEmpty } from 'lodash'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { getDatasetDisplayName } from '../../../common/utils/get_dataset_display_name'; import { truthy } from '../../../../common/utils/helpers'; import { CSP_MOMENT_FORMAT } from '../../../common/constants'; import { INTERNAL_FEATURE_FLAGS, CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX, - CDR_MISCONFIGURATIONS_INDEX_PATTERN, } from '../../../../common/constants'; import { useDataView } from '../../../common/api/use_data_view'; import { useKibana } from '../../../common/hooks/use_kibana'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; import { BenchmarkIcons, CodeBlock, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/rule_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/rule_tab.tsx index 6a7eea41410e9..26007205f43fe 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/rule_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/rule_tab.tsx @@ -9,7 +9,7 @@ import { EuiBadge, EuiDescriptionList } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { RulesDetectionRuleCounter } from '../../rules/rules_detection_rule_counter'; import { BenchmarkIcons, CspFlyoutMarkdown, EMPTY_VALUE, RuleNameLink } from './findings_flyout'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/table_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/table_tab.tsx index 075291c434592..ad449c4ddccdc 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/table_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/table_tab.tsx @@ -15,7 +15,7 @@ import { import React from 'react'; import { getFlattenedObject } from '@kbn/std'; import { i18n } from '@kbn/i18n'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; interface FlattenedItem { key: string; // flattened dot notation object path for CspFinding; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_table.tsx index 2d9e1c3f25ae1..209c5ed2b2d06 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_table.tsx @@ -11,7 +11,7 @@ import { DataTableRecord } from '@kbn/discover-utils/types'; import { HttpSetup } from '@kbn/core-http-browser'; import { i18n } from '@kbn/i18n'; import { EuiDataGridCellValueElementProps, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { getDatasetDisplayName } from '../../../common/utils/get_dataset_display_name'; import * as TEST_SUBJECTS from '../test_subjects'; import { FindingsDistributionBar } from '../layout/findings_distribution_bar'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts index ceada5c3148eb..cf79ef80b1196 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts @@ -6,11 +6,11 @@ */ import { useQuery } from '@tanstack/react-query'; -import { CspBenchmarkRulesStates } from '../../../../common/types/latest'; import { CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION, CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH, -} from '../../../../common/constants'; +} from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../../../common/hooks/use_kibana'; export const getRuleStatesKey = ['get_rules_state_key']; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx index 9c1125257520e..532998f0f712f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx @@ -10,7 +10,7 @@ import type { IKibanaSearchResponse } from '@kbn/search-types'; import { GenericBuckets, GroupingQuery, RootAggregation } from '@kbn/grouping/src'; import { useQuery } from '@tanstack/react-query'; import { lastValueFrom } from 'rxjs'; -import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '../../../../common/constants'; +import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../../../common/hooks/use_kibana'; import { showErrorToast } from '../../../common/utils/show_error_toast'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts index 3af41c5921416..5a77337ba171c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts @@ -11,18 +11,17 @@ import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-ty import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { EsHitRecord } from '@kbn/discover-utils/types'; -import { CspFinding } from '../../../../common/schemas/csp_finding'; -import { useKibana } from '../../../common/hooks/use_kibana'; -import type { FindingsBaseEsQuery } from '../../../common/types'; -import { getAggregationCount, getFindingsCountAggQuery } from '../utils/utils'; +import { MAX_FINDINGS_TO_LOAD } from '@kbn/cloud-security-posture-common'; import { CDR_MISCONFIGURATIONS_INDEX_PATTERN, LATEST_FINDINGS_RETENTION_POLICY, -} from '../../../../common/constants'; -import { MAX_FINDINGS_TO_LOAD } from '../../../common/constants'; +} from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates, CspFinding } from '@kbn/cloud-security-posture-common'; +import type { FindingsBaseEsQuery } from '@kbn/cloud-security-posture'; +import { useKibana } from '../../../common/hooks/use_kibana'; +import { getAggregationCount, getFindingsCountAggQuery } from '../utils/utils'; import { showErrorToast } from '../../../common/utils/show_error_toast'; import { useGetCspBenchmarkRulesStatesApi } from './use_get_benchmark_rules_state_api'; -import { CspBenchmarkRulesStates } from '../../../../common/types/latest'; import { buildMutedRulesFilter } from '../../../../common/utils/rules_states'; interface UseFindingsOptions extends FindingsBaseEsQuery { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx index 0235960207e27..d94f063933b0e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx @@ -15,13 +15,13 @@ import { } from '@kbn/grouping/src'; import { useMemo } from 'react'; import { buildEsQuery, Filter } from '@kbn/es-query'; +import { LATEST_FINDINGS_RETENTION_POLICY } from '@kbn/cloud-security-posture-common'; import { FINDINGS_GROUPING_OPTIONS, LOCAL_STORAGE_FINDINGS_GROUPING_KEY, } from '../../../common/constants'; import { useDataViewContext } from '../../../common/contexts/data_view_context'; import { Evaluation } from '../../../../common/types_old'; -import { LATEST_FINDINGS_RETENTION_POLICY } from '../../../../common/constants'; import { FindingsGroupingAggregation, FindingsRootGroupingAggregation, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx index 755ecb86c73ba..61d4a5cc7d6dc 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx @@ -10,10 +10,10 @@ import { EuiThemeComputed, useEuiTheme } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { i18n } from '@kbn/i18n'; import type { Filter } from '@kbn/es-query'; +import type { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import { useDataViewContext } from '../../../common/contexts/data_view_context'; import { SecuritySolutionContext } from '../../../application/security_solution_context'; import type { FindingsBaseURLQuery } from '../../../common/types'; -import type { CspClientPluginStartDeps } from '../../../types'; import { PLUGIN_NAME } from '../../../../common'; type SearchBarQueryProps = Pick; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts index d77e6ddf6389c..289c6c2cb153f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts @@ -6,11 +6,10 @@ */ import { HttpSetup } from '@kbn/core/public'; +import { LATEST_FINDINGS_RETENTION_POLICY } from '@kbn/cloud-security-posture-common'; import { CspBenchmarkRule } from '../../../../common/types/latest'; -import { - FINDINGS_INDEX_PATTERN, - LATEST_FINDINGS_RETENTION_POLICY, -} from '../../../../common/constants'; +import { FINDINGS_INDEX_PATTERN } from '../../../../common/constants'; + import { createDetectionRule } from '../../../common/api/create_detection_rule'; import { generateBenchmarkRuleTags } from '../../../../common/utils/detection_rules'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx index 391cbdd5c63f2..0bafc004a5e11 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx @@ -23,7 +23,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { HttpSetup } from '@kbn/core/public'; -import { CspBenchmarkRuleMetadata } from '../../../common/types/latest'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; import { getRuleList } from '../configurations/findings_flyout/rule_tab'; import { getRemediationList } from '../configurations/findings_flyout/overview_tab'; import * as TEST_SUBJECTS from './test_subjects'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts index e712b130e1651..640dc92274481 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts @@ -6,8 +6,8 @@ */ import { useQuery } from '@tanstack/react-query'; -import { CspBenchmarkRulesStates } from '../../../common/types/latest'; -import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '../../../common/constants'; +import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; import { useKibana } from '../../common/hooks/use_kibana'; export const CSP_RULES_STATES_QUERY_KEY = ['csp_rules_states_v1']; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx index 15760e80ad7c2..3b1d3a156f305 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx @@ -16,7 +16,9 @@ import { } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { EsHitRecord } from '@kbn/discover-utils/types'; -import { MAX_FINDINGS_TO_LOAD, VULNERABILITY_FIELDS } from '../../../common/constants'; +import { MAX_FINDINGS_TO_LOAD } from '@kbn/cloud-security-posture-common'; +import { FindingsBaseEsQuery } from '@kbn/cloud-security-posture'; +import { VULNERABILITY_FIELDS } from '../../../common/constants'; import { CspVulnerabilityFinding } from '../../../../common/schemas'; import { LATEST_VULNERABILITIES_INDEX_PATTERN, @@ -24,7 +26,6 @@ import { } from '../../../../common/constants'; import { useKibana } from '../../../common/hooks/use_kibana'; import { showErrorToast } from '../../../common/utils/show_error_toast'; -import { FindingsBaseEsQuery } from '../../../common/types'; import { getCaseInsensitiveSortScript } from '../utils/custom_sort_script'; type LatestFindingsRequest = IKibanaSearchRequest; type LatestFindingsResponse = IKibanaSearchResponse< diff --git a/x-pack/plugins/cloud_security_posture/public/plugin.tsx b/x-pack/plugins/cloud_security_posture/public/plugin.tsx index bf014f83c1b0d..d07d930660ec6 100755 --- a/x-pack/plugins/cloud_security_posture/public/plugin.tsx +++ b/x-pack/plugins/cloud_security_posture/public/plugin.tsx @@ -9,14 +9,10 @@ import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; +import type { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import { CspLoadingState } from './components/csp_loading_state'; import type { CspRouterProps } from './application/csp_router'; -import type { - CspClientPluginSetup, - CspClientPluginStart, - CspClientPluginSetupDeps, - CspClientPluginStartDeps, -} from './types'; +import type { CspClientPluginSetup, CspClientPluginStart, CspClientPluginSetupDeps } from './types'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../common/constants'; import { SetupContext } from './application/setup_context'; diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts index fb7a25fbcdadf..62430421f7358 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts @@ -6,10 +6,8 @@ */ import { http, HttpResponse } from 'msw'; -import { - CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX, - CDR_MISCONFIGURATIONS_INDEX_PATTERN, -} from '../../../../common/constants'; +import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; +import { CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX } from '../../../../common/constants'; const generateDataViewField = (name: string, type: 'string' | 'date' = 'string') => ({ name, diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts index 999f130c275cc..86ec3e3108f27 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts @@ -13,9 +13,9 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { indexPatternFieldEditorPluginMock as dataViewFieldEditorMock } from '@kbn/data-view-field-editor-plugin/public/mocks'; import SearchBar from '@kbn/unified-search-plugin/public/search_bar/search_bar'; import { http, HttpResponse, JsonBodyType } from 'msw'; +import { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import { defaultHandlers } from './handlers'; import { getMockDependencies } from '../fixtures/get_mock_dependencies'; -import { CspClientPluginStartDeps } from '../../types'; import { MOCK_SERVER_LICENSING_INFO_URL } from './handlers/licensing.handlers.mock'; /** diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx index 19143d4641836..0a2db4ca59643 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import type { CoreStart } from '@kbn/core/public'; -import { CspClientPluginStartDeps } from '../../types'; +import { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import { TestProvider } from '../test_provider'; import { getMockServerDependencies } from './mock_server'; interface MockServerDependencies { diff --git a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx index ab3173ec8c581..278ba2f0b1690 100755 --- a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx +++ b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx @@ -14,7 +14,7 @@ import { Route, Routes } from '@kbn/shared-ux-router'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { coreMock } from '@kbn/core/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import type { CspClientPluginStartDeps } from '../types'; +import type { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; import { getMockDependencies } from './fixtures/get_mock_dependencies'; interface CspAppDeps { diff --git a/x-pack/plugins/cloud_security_posture/public/types.ts b/x-pack/plugins/cloud_security_posture/public/types.ts index bd45c007112b0..f03d47e43575d 100755 --- a/x-pack/plugins/cloud_security_posture/public/types.ts +++ b/x-pack/plugins/cloud_security_posture/public/types.ts @@ -6,26 +6,12 @@ */ import type { CloudSetup } from '@kbn/cloud-plugin/public'; -import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; -import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { ComponentType, ReactNode } from 'react'; -import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; -import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; -import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { CoreStart, ToastsStart } from '@kbn/core/public'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; - -import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; -import type { DiscoverStart } from '@kbn/discover-plugin/public'; -import type { FleetSetup, FleetStart } from '@kbn/fleet-plugin/public'; -import type { - UsageCollectionSetup, - UsageCollectionStart, -} from '@kbn/usage-collection-plugin/public'; -import { SharePluginStart } from '@kbn/share-plugin/public'; -import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; +import { UiActionsSetup } from '@kbn/ui-actions-plugin/public'; +import type { DataPublicPluginSetup } from '@kbn/data-plugin/public'; +import { CoreStart } from '@kbn/core/public'; +import type { FleetSetup } from '@kbn/fleet-plugin/public'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { CspRouterProps } from './application/csp_router'; import type { CloudSecurityPosturePageId } from './common/navigation/types'; @@ -53,28 +39,6 @@ export interface CspClientPluginSetupDeps { usageCollection?: UsageCollectionSetup; } -export interface CspClientPluginStartDeps { - // required - data: DataPublicPluginStart; - dataViews: DataViewsServicePublic; - dataViewFieldEditor: IndexPatternFieldEditorStart; - unifiedSearch: UnifiedSearchPublicPluginStart; - uiActions: UiActionsStart; - fieldFormats: FieldFormatsStart; - toastNotifications: ToastsStart; - charts: ChartsPluginStart; - discover: DiscoverStart; - fleet: FleetStart; - licensing: LicensingPluginStart; - share: SharePluginStart; - storage: Storage; - spaces: SpacesPluginStart; - cloud: CloudSetup; - - // optional - usageCollection?: UsageCollectionStart; -} - /** * Methods exposed from the security solution to the cloud security posture application. */ diff --git a/x-pack/plugins/cloud_security_posture/server/create_indices/latest_indices.ts b/x-pack/plugins/cloud_security_posture/server/create_indices/latest_indices.ts index 91c7ae74de9e8..2994c88bef290 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_indices/latest_indices.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_indices/latest_indices.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import { FINDINGS_INDEX_NAME, - CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN, LATEST_FINDINGS_INDEX_TEMPLATE_NAME, LATEST_FINDINGS_INDEX_DEFAULT_NS, VULNERABILITIES_INDEX_NAME, diff --git a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts index 556ab0c7c830c..aa428c7083eca 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts @@ -5,11 +5,11 @@ * 2.0. */ import type { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; +import { LATEST_FINDINGS_RETENTION_POLICY } from '@kbn/cloud-security-posture-common'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, FINDINGS_INDEX_PATTERN, LATEST_FINDINGS_INDEX_DEFAULT_NS, - LATEST_FINDINGS_RETENTION_POLICY, } from '../../common/constants'; const LATEST_FINDINGS_TRANSFORM_V830 = 'cloud_security_posture.findings_latest-default-0.0.1'; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts index 67eb611f9557e..85d4a7f76a5c9 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts @@ -6,8 +6,9 @@ */ import { ElasticsearchClient, type Logger } from '@kbn/core/server'; +import type { IndexStatus } from '@kbn/cloud-security-posture-common'; import { getSafePostureTypeRuntimeMapping } from '../../common/runtime_mappings/get_safe_posture_type_runtime_mapping'; -import { IndexStatus, PostureTypes } from '../../common/types_old'; +import { PostureTypes } from '../../common/types_old'; export interface PostureTypeAndRetention { postureType?: PostureTypes; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts index 5a11ddebdd9d3..a82eeb70c3d40 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts @@ -5,6 +5,7 @@ * 2.0. */ import { flatMap, uniq } from 'lodash'; +import { KSPM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; import type { AgentPolicyServiceInterface, @@ -23,8 +24,6 @@ import { CloudSecurityPolicyTemplate, PostureTypes } from '../../common/types_ol import { SUPPORTED_POLICY_TEMPLATES, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, - KSPM_POLICY_TEMPLATE, - CSPM_POLICY_TEMPLATE, } from '../../common/constants'; import { CSP_FLEET_PACKAGE_KUERY } from '../../common/utils/helpers'; import { diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/cloud_accounts_stats_collector.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/cloud_accounts_stats_collector.ts index 5cd7c6dc03766..32043329b0706 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/cloud_accounts_stats_collector.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/cloud_accounts_stats_collector.ts @@ -6,6 +6,7 @@ */ import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import type { ISavedObjectsRepository, Logger } from '@kbn/core/server'; +import { KSPM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { getPackagePolicyIdRuntimeMapping } from '../../../../common/runtime_mappings/get_package_policy_id_mapping'; import { getIdentifierRuntimeMapping } from '../../../../common/runtime_mappings/get_identifier_runtime_mapping'; @@ -17,8 +18,6 @@ import type { CloudSecurityAccountsStats, } from './types'; import { - CSPM_POLICY_TEMPLATE, - KSPM_POLICY_TEMPLATE, LATEST_FINDINGS_INDEX_DEFAULT_NS, LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, VULN_MGMT_POLICY_TEMPLATE, diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts index d5db37879554b..baa4601565c85 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts @@ -6,7 +6,7 @@ */ import { AggregationsMultiBucketBase } from '@elastic/elasticsearch/lib/api/types'; -import { CspStatusCode } from '../../../../common/types_old'; +import { CspStatusCode } from '@kbn/cloud-security-posture-common'; export type CloudSecurityUsageCollectorType = | 'Indices' diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts index 820194b0b9cd6..e733f6cc96003 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts @@ -6,12 +6,12 @@ */ import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; import type { FindResult, RulesClient } from '@kbn/alerting-plugin/server'; import type { RuleParams } from '@kbn/alerting-plugin/server/application/rule/types'; import type { CspBenchmarkRule, RulesToUpdate, - CspBenchmarkRulesStates, CspSettings, } from '../../../../common/types/rules/v4'; import { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts index a55bcd92ab3c8..44dd77cc67059 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts @@ -6,9 +6,9 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; +import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; import { CspRouter } from '../../../types'; -import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '../../../../common/constants'; -import { CspBenchmarkRulesStates } from '../../../../common/types/rules/v4'; import { getCspBenchmarkRulesStatesHandler } from './v1'; export const defineGetCspBenchmarkRulesStatesRoute = (router: CspRouter) => diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts index 4d28b995cbdaf..1c7ddccf91bba 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts @@ -10,7 +10,8 @@ import { } from '@kbn/core-saved-objects-api-server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { CspBenchmarkRulesStates, CspSettings } from '../../../../common/types/rules/v4'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; +import { CspSettings } from '../../../../common/types/rules/v4'; import { INTERNAL_CSP_SETTINGS_SAVED_OBJECT_ID, INTERNAL_CSP_SETTINGS_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts index e793863621340..4cb7ec3c918e6 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts @@ -15,7 +15,7 @@ import type { } from '@elastic/elasticsearch/lib/api/types'; import type { Logger } from '@kbn/core/server'; import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; -import { CspFinding } from '../../../common/schemas/csp_finding'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; import type { Cluster } from '../../../common/types_old'; import { getPostureStatsFromAggs, failedFindingsAggQuery } from './get_grouped_findings_evaluation'; import type { FailedFindingsQueryResult } from './get_grouped_findings_evaluation'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts index 24d213b92ad8b..e3b844a551a4e 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts @@ -5,8 +5,9 @@ * 2.0. */ +import { CSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import { calculateIntegrationStatus } from './status'; -import { CSPM_POLICY_TEMPLATE, VULN_MGMT_POLICY_TEMPLATE } from '../../../common/constants'; +import { VULN_MGMT_POLICY_TEMPLATE } from '../../../common/constants'; import { Installation } from '@kbn/fleet-plugin/common'; const mockInstallation: Installation = { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts index 868deaed0fd82..2434cf03c8473 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts @@ -6,6 +6,18 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; +import { + KSPM_POLICY_TEMPLATE, + CSPM_POLICY_TEMPLATE, + STATUS_ROUTE_PATH, + LATEST_FINDINGS_RETENTION_POLICY, + CDR_MISCONFIGURATIONS_INDEX_PATTERN, +} from '@kbn/cloud-security-posture-common'; +import type { + CspSetupStatus, + IndexStatus, + CspStatusCode, +} from '@kbn/cloud-security-posture-common'; import type { SavedObjectsClientContract, Logger, ElasticsearchClient } from '@kbn/core/server'; import type { AgentPolicyServiceInterface, @@ -19,20 +31,15 @@ import { schema } from '@kbn/config-schema'; import { VersionedRoute } from '@kbn/core-http-server/src/versioning/types'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, - STATUS_ROUTE_PATH, LATEST_FINDINGS_INDEX_DEFAULT_NS, FINDINGS_INDEX_PATTERN, BENCHMARK_SCORE_INDEX_DEFAULT_NS, VULNERABILITIES_INDEX_PATTERN, - KSPM_POLICY_TEMPLATE, - CSPM_POLICY_TEMPLATE, POSTURE_TYPES, LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, VULN_MGMT_POLICY_TEMPLATE, POSTURE_TYPE_ALL, LATEST_VULNERABILITIES_RETENTION_POLICY, - LATEST_FINDINGS_RETENTION_POLICY, - CDR_MISCONFIGURATIONS_INDEX_PATTERN, } from '../../../common/constants'; import type { CspApiRequestHandlerContext, @@ -40,12 +47,7 @@ import type { CspRouter, StatusResponseInfo, } from '../../types'; -import type { - CspSetupStatus, - CspStatusCode, - IndexStatus, - PostureTypes, -} from '../../../common/types_old'; +import type { PostureTypes } from '../../../common/types_old'; import { getAgentStatusesByAgentPolicies, getCspAgentPolicies, diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/data_views.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/data_views.ts index 8a9f44b3aec46..e99f0365e6099 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/data_views.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/data_views.ts @@ -15,11 +15,11 @@ import { DataViewAttributes } from '@kbn/data-views-plugin/common'; import { SpacesServiceStart } from '@kbn/spaces-plugin/server'; import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; +import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import { CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX, CDR_MISCONFIGURATIONS_DATA_VIEW_NAME, - CDR_MISCONFIGURATIONS_INDEX_PATTERN, CDR_VULNERABILITIES_DATA_VIEW_ID_PREFIX, CDR_VULNERABILITIES_DATA_VIEW_NAME, CDR_VULNERABILITIES_INDEX_PATTERN, diff --git a/x-pack/plugins/cloud_security_posture/server/types.ts b/x-pack/plugins/cloud_security_posture/server/types.ts index 1190c0a1c5556..4524cab151dd2 100644 --- a/x-pack/plugins/cloud_security_posture/server/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/types.ts @@ -30,12 +30,12 @@ import type { PackagePolicyClient, } from '@kbn/fleet-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { CspStatusCode, IndexDetails } from '@kbn/cloud-security-posture-common'; import type { FleetStartContract, FleetRequestHandlerContext } from '@kbn/fleet-plugin/server'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server'; import type { AlertingPluginSetup } from '@kbn/alerting-plugin/public/plugin'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; -import { CspStatusCode, IndexDetails } from '../common/types_old'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CspServerPluginSetup {} diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json index 83891e3269eca..6e19e9b4d09fa 100755 --- a/x-pack/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/plugins/cloud_security_posture/tsconfig.json @@ -57,7 +57,6 @@ "@kbn/kibana-utils-plugin", "@kbn/ui-actions-plugin", "@kbn/core-http-server-mocks", - "@kbn/field-formats-plugin", "@kbn/data-view-field-editor-plugin", "@kbn/grouping", "@kbn/alerting-plugin", @@ -65,7 +64,9 @@ "@kbn/code-editor-mock", "@kbn/search-types", "@kbn/react-kibana-mount", - "@kbn/spaces-plugin" + "@kbn/spaces-plugin", + "@kbn/cloud-security-posture-common", + "@kbn/cloud-security-posture" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/security_solution_serverless/server/cloud_security/constants.ts b/x-pack/plugins/security_solution_serverless/server/cloud_security/constants.ts index cd5a6a79eed33..8eb74f781096a 100644 --- a/x-pack/plugins/security_solution_serverless/server/cloud_security/constants.ts +++ b/x-pack/plugins/security_solution_serverless/server/cloud_security/constants.ts @@ -6,10 +6,12 @@ */ import { - CNVM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE, CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN, +} from '@kbn/cloud-security-posture-common'; +import { + CNVM_POLICY_TEMPLATE, LATEST_VULNERABILITIES_INDEX_PATTERN, } from '@kbn/cloud-security-posture-plugin/common/constants'; import { INTEGRATION_PACKAGE_NAME } from '@kbn/cloud-defend-plugin/common/constants'; diff --git a/x-pack/plugins/security_solution_serverless/tsconfig.json b/x-pack/plugins/security_solution_serverless/tsconfig.json index b6bfbea1cc7be..55a4882655dc7 100644 --- a/x-pack/plugins/security_solution_serverless/tsconfig.json +++ b/x-pack/plugins/security_solution_serverless/tsconfig.json @@ -45,5 +45,6 @@ "@kbn/discover-plugin", "@kbn/logging", "@kbn/integration-assistant-plugin", + "@kbn/cloud-security-posture-common", ] } diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts index 199cacf99dea2..13bc2ee7de9d2 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts @@ -9,7 +9,7 @@ import type { Agent as SuperTestAgent } from 'supertest'; import { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { IndexDetails } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { IndexDetails } from '@kbn/cloud-security-posture-common'; import { CLOUD_SECURITY_PLUGIN_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import { SecurityService } from '@kbn/test-suites-src/common/services/security/security'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts index 3eda0f6a7b01a..b82140727fc24 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts index 5e6d639490e45..1793944480ac7 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts index f55f5533718ed..ab8345284380a 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts index f67e2d5a0814b..ef442c575981a 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts index e80e80c322568..fe234e45e21f0 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts index a148f160bfd81..bfb5321bdcba9 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { setupFleetAndAgents } from '../../../../fleet_api_integration/apis/agents/services'; import { generateAgent } from '../../../../fleet_api_integration/helpers'; import { FtrProviderContext } from '../../../ftr_provider_context'; diff --git a/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts b/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts index 6716cc859f278..ae51bbdf9e154 100644 --- a/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts +++ b/x-pack/test/cloud_security_posture_api/routes/helper/user_roles_utilites.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; import { - CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN, BENCHMARK_SCORE_INDEX_PATTERN, LATEST_VULNERABILITIES_INDEX_PATTERN, ALERTS_INDEX_PATTERN, diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 160aa0a3d81f6..1173ef6b4d492 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -179,6 +179,7 @@ "@kbn/cases-api-integration-test-plugin", "@kbn/security-solution-plugin/public/management/cypress", "@kbn/management-settings-ids", - "@kbn/mock-idp-utils" + "@kbn/mock-idp-utils", + "@kbn/cloud-security-posture-common" ] } diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts index 1b44c42ecb22e..ff0208459856f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts index 4e81938a597e9..80a07bd6ee79c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts index eb7b6f4424c0d..d3510ea98b7bb 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { createPackagePolicy } from '@kbn/test-suites-xpack/api_integration/apis/cloud_security_posture/helper'; import { FtrProviderContext } from '../../../../ftr_provider_context'; diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index 36aaf983bae08..7a7747a964caa 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -97,5 +97,6 @@ "@kbn/ml-trained-models-utils", "@kbn/test-suites-src", "@kbn/console-plugin", + "@kbn/cloud-security-posture-common", ] } From b98a8d313d49fb9eec1eea6638ebcaab07c076ad Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Tue, 27 Aug 2024 10:12:22 +0200 Subject: [PATCH 20/38] [Infra] Attempt to fix APMEventClient unit test (#191268) closes [190703](https://github.com/elastic/kibana/issues/190703) ## Summary I'm not sure if this change will resolve the flakiness. What I discovered is that the test had an open handle due to an unfinished promise. Co-authored-by: Elastic Machine --- .../create_es_client/create_apm_event_client/index.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts index 9cab31e30af64..c2a5676e85c28 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts @@ -36,7 +36,9 @@ describe('APMEventClient', () => { esClient: { search: async (params: any, { signal }: { signal: AbortSignal }) => { abortSignal = signal; - await setTimeoutPromise(3_000); + await setTimeoutPromise(3_000, undefined, { + signal: abortSignal, + }); return {}; }, } as any, From 5075b046cf3f2e99f0b15bf9fbb0cf6d4fbce725 Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Tue, 27 Aug 2024 10:18:52 +0200 Subject: [PATCH 21/38] [Fleet] Implement preconditions in packages install state machine (#190986) Closes https://github.com/elastic/kibana/issues/189353 ## Summary Small change that implements a precondition function for package install state machine. This is needed for the subsequent work planned in https://github.com/elastic/kibana/issues/169147. Note that this code is added and tested, but it's not currently used and it will actually be used only when https://github.com/elastic/kibana/issues/175597 will be implemented. ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Elastic Machine --- .../state_machine.test.ts | 420 +++++++++++------- .../install_state_machine/state_machine.ts | 32 ++ 2 files changed, 285 insertions(+), 167 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.test.ts index f6e1f8fba5a20..795440025c7fd 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.test.ts @@ -10,29 +10,40 @@ import { appContextService } from '../../..'; import { handleState } from './state_machine'; -const getTestDefinition = ( - mockOnTransition1: any, - mockOnTransition2: any, - mockOnTransition3: any, - context?: any, - onPostTransition?: any -) => { +const getTestDefinition = ({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + mockPostTransition, + mockPreTransition, +}: { + mockOnTransition1: any; + mockOnTransition2: any; + mockOnTransition3: any; + context?: any; + mockPostTransition?: any; + mockPreTransition?: any; +}) => { return { context, states: { state1: { + onPreTransition: mockPreTransition, onTransition: mockOnTransition1, - onPostTransition, + onPostTransition: mockPostTransition, nextState: 'state2', }, state2: { + onPreTransition: mockPreTransition, onTransition: mockOnTransition2, - onPostTransition, + onPostTransition: mockPostTransition, nextState: 'state3', }, state3: { + onPreTransition: mockPreTransition, onTransition: mockOnTransition3, - onPostTransition, + onPostTransition: mockPostTransition, nextState: 'end', }, }, @@ -52,19 +63,19 @@ describe('handleState', () => { }); it('should execute all the state machine transitions based on the provided data structure', async () => { - const mockOnTransitionState1 = jest.fn(); - const mockOnTransitionState2 = jest.fn(); - const mockOnTransitionState3 = jest.fn(); - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3 - ); + const mockOnTransition1 = jest.fn(); + const mockOnTransition2 = jest.fn(); + const mockOnTransition3 = jest.fn(); + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + }); await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(1); - expect(mockOnTransitionState2).toHaveBeenCalledTimes(1); - expect(mockOnTransitionState3).toHaveBeenCalledTimes(1); + expect(mockOnTransition1).toHaveBeenCalledTimes(1); + expect(mockOnTransition2).toHaveBeenCalledTimes(1); + expect(mockOnTransition3).toHaveBeenCalledTimes(1); expect(mockContract.logger?.debug).toHaveBeenCalledWith( 'Executed state: state1 with status: success - nextState: state2' ); @@ -77,22 +88,22 @@ describe('handleState', () => { }); it('should call the onTransition function with context data and the return value is saved for the next iteration', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ arrayData: ['test1', 'test2'] }); - const mockOnTransitionState2 = jest + const mockOnTransition1 = jest.fn().mockReturnValue({ arrayData: ['test1', 'test2'] }); + const mockOnTransition2 = jest .fn() .mockImplementation(() => Promise.resolve({ promiseData: {} })); - const mockOnTransitionState3 = jest.fn().mockReturnValue({ lastData: ['test3'] }); - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition3 = jest.fn().mockReturnValue({ lastData: ['test3'] }); + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledWith({ testData: 'test' }); - expect(mockOnTransitionState2).toHaveBeenCalledWith( + expect(mockOnTransition1).toHaveBeenCalledWith({ testData: 'test' }); + expect(mockOnTransition2).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', arrayData: ['test1', 'test2'], @@ -102,7 +113,7 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState3).toHaveBeenCalledWith( + expect(mockOnTransition3).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', arrayData: ['test1', 'test2'], @@ -126,27 +137,27 @@ describe('handleState', () => { }); it('should save the return data from transitions also when return type is function', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ arrayData: ['test1', 'test2'] }); + const mockOnTransition1 = jest.fn().mockReturnValue({ arrayData: ['test1', 'test2'] }); const state2Result = () => { return { result: 'test', }; }; - const mockOnTransitionState2 = jest.fn().mockImplementation(() => { + const mockOnTransition2 = jest.fn().mockImplementation(() => { return state2Result; }); - const mockOnTransitionState3 = jest.fn(); - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition3 = jest.fn(); + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledWith({ testData: 'test' }); - expect(mockOnTransitionState2).toHaveBeenCalledWith( + expect(mockOnTransition1).toHaveBeenCalledWith({ testData: 'test' }); + expect(mockOnTransition2).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', arrayData: ['test1', 'test2'], @@ -157,7 +168,7 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState3).toHaveBeenCalledWith( + expect(mockOnTransition3).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', arrayData: ['test1', 'test2'], @@ -181,7 +192,7 @@ describe('handleState', () => { }); it('should return updated context data', async () => { - const mockOnTransitionState1 = jest + const mockOnTransition1 = jest .fn() .mockImplementation(() => Promise.resolve({ promiseData: {} })); const state2Result = () => { @@ -189,21 +200,21 @@ describe('handleState', () => { result: 'test', }; }; - const mockOnTransitionState2 = jest.fn().mockImplementation(() => { + const mockOnTransition2 = jest.fn().mockImplementation(() => { return state2Result; }); - const mockOnTransitionState3 = jest.fn().mockReturnValue({ lastData: ['test3'] }); - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition3 = jest.fn().mockReturnValue({ lastData: ['test3'] }); + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); const updatedContext = await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledWith({ testData: 'test' }); - expect(mockOnTransitionState2).toHaveBeenCalledWith( + expect(mockOnTransition1).toHaveBeenCalledWith({ testData: 'test' }); + expect(mockOnTransition2).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', promiseData: {}, @@ -214,7 +225,7 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState3).toHaveBeenCalledWith( + expect(mockOnTransition3).toHaveBeenCalledWith( expect.objectContaining({ testData: 'test', promiseData: {}, @@ -241,22 +252,22 @@ describe('handleState', () => { }); it('should update a variable in the context at every call and return the updated value', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); - const mockOnTransitionState2 = jest + const mockOnTransition1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); + const mockOnTransition2 = jest .fn() .mockImplementation(() => Promise.resolve({ runningVal: 'test2' })); - const mockOnTransitionState3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); - const contextData = { runningVal: [], fixedVal: 'something' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); + const context = { runningVal: [], fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); const updatedContext = await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledWith({ runningVal: [], fixedVal: 'something' }); - expect(mockOnTransitionState2).toHaveBeenCalledWith( + expect(mockOnTransition1).toHaveBeenCalledWith({ runningVal: [], fixedVal: 'something' }); + expect(mockOnTransition2).toHaveBeenCalledWith( expect.objectContaining({ runningVal: 'test1', fixedVal: 'something', @@ -266,7 +277,7 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState3).toHaveBeenCalledWith( + expect(mockOnTransition3).toHaveBeenCalledWith( expect.objectContaining({ runningVal: 'test2', fixedVal: 'something', @@ -289,29 +300,29 @@ describe('handleState', () => { }); it('should execute the transition starting from the provided state', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); - const mockOnTransitionState2 = jest + const mockOnTransition1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); + const mockOnTransition2 = jest .fn() .mockImplementation(() => Promise.resolve({ runningVal: 'test2' })); - const mockOnTransitionState3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); - const contextData = { runningVal: [], fixedVal: 'something' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); + const context = { runningVal: [], fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); const updatedContext = await handleState('state2', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(0); - expect(mockOnTransitionState2).toHaveBeenCalledWith( + expect(mockOnTransition1).toHaveBeenCalledTimes(0); + expect(mockOnTransition2).toHaveBeenCalledWith( expect.objectContaining({ runningVal: [], fixedVal: 'something', }) ); - expect(mockOnTransitionState3).toHaveBeenCalledWith( + expect(mockOnTransition3).toHaveBeenCalledWith( expect.objectContaining({ runningVal: 'test2', fixedVal: 'something', @@ -335,46 +346,121 @@ describe('handleState', () => { it('should throw and return updated context with latest error when a state returns error', async () => { const error = new Error('Installation failed'); - const mockOnTransitionState1 = jest.fn().mockRejectedValue(error); - const mockOnTransitionState2 = jest.fn(); - const mockOnTransitionState3 = jest.fn(); - const contextData = { fixedVal: 'something' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition1 = jest.fn().mockRejectedValue(error); + const mockOnTransition2 = jest.fn(); + const mockOnTransition3 = jest.fn(); + const context = { fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); const promise = handleState('state1', testDefinition, testDefinition.context); await expect(promise).rejects.toThrowError('Installation failed'); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(1); - expect(mockOnTransitionState2).toHaveBeenCalledTimes(0); - expect(mockOnTransitionState3).toHaveBeenCalledTimes(0); + expect(mockOnTransition1).toHaveBeenCalledTimes(1); + expect(mockOnTransition2).toHaveBeenCalledTimes(0); + expect(mockOnTransition3).toHaveBeenCalledTimes(0); expect(mockContract.logger?.warn).toHaveBeenCalledWith( 'Error during execution of state "state1" with status "failed": Installation failed' ); }); + it('should execute preTransition function before the transition gets executed', async () => { + const mockOnTransition1 = jest.fn(); + const mockOnTransition2 = jest.fn(); + const mockOnTransition3 = jest.fn(); + const mockPreTransition = jest.fn(); + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + mockPreTransition, + }); + await handleState('state1', testDefinition, testDefinition.context); + + expect(mockPreTransition).toHaveBeenCalled(); + expect(mockOnTransition1).toHaveBeenCalled(); + + expect(mockContract.logger?.debug).toHaveBeenCalledWith( + 'Executing pre transition function: mockConstructor' + ); + }); + + it('should execute preTransition function before the transition gets executed passing the updated context', async () => { + const mockPreTransition = jest.fn().mockReturnValue({ runningVal: 'test1' }); + const mockOnTransition1 = jest.fn(); + const mockOnTransition2 = jest + .fn() + .mockImplementation(() => Promise.resolve({ runningVal: 'test2' })); + const mockOnTransition3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); + const context = { fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + mockPreTransition, + context, + }); + const updatedContext = await handleState('state1', testDefinition, testDefinition.context); + + expect(updatedContext).toEqual( + expect.objectContaining({ + fixedVal: 'something', + runningVal: 'test3', + latestExecutedState: { + name: 'state3', + started_at: expect.anything(), + }, + }) + ); + }); + + it('should throw error and not execute subsequent transitions when onPreTransition throws error', async () => { + const error = new Error('Precondition failed'); + const mockPreTransition = jest.fn().mockRejectedValue(error); + const mockOnTransition1 = jest.fn(); + const mockOnTransition2 = jest.fn(); + + const mockOnTransition3 = jest.fn(); + const context = { fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + mockPreTransition, + context, + }); + + await expect( + handleState('state1', testDefinition, testDefinition.context) + ).rejects.toThrowError('Precondition failed'); + + expect(mockPreTransition).toHaveBeenCalled(); + expect(mockOnTransition1).not.toHaveBeenCalled(); + expect(mockOnTransition2).not.toHaveBeenCalled(); + expect(mockOnTransition3).not.toHaveBeenCalled(); + }); + it('should execute postTransition function after the transition is complete', async () => { - const mockOnTransitionState1 = jest.fn(); - const mockOnTransitionState2 = jest.fn(); - const mockOnTransitionState3 = jest.fn(); + const mockOnTransition1 = jest.fn(); + const mockOnTransition2 = jest.fn(); + const mockOnTransition3 = jest.fn(); const mockPostTransition = jest.fn(); - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - undefined, - mockPostTransition - ); + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + mockPostTransition, + }); await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalled(); + expect(mockOnTransition1).toHaveBeenCalled(); expect(mockPostTransition).toHaveBeenCalled(); - expect(mockOnTransitionState2).toHaveBeenCalled(); + expect(mockOnTransition2).toHaveBeenCalled(); expect(mockPostTransition).toHaveBeenCalled(); - expect(mockOnTransitionState3).toHaveBeenCalled(); + expect(mockOnTransition3).toHaveBeenCalled(); expect(mockPostTransition).toHaveBeenCalled(); expect(mockContract.logger?.debug).toHaveBeenCalledWith( 'Executing post transition function: mockConstructor' @@ -382,27 +468,27 @@ describe('handleState', () => { }); it('should execute postTransition function after the transition passing the updated context', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); - const mockOnTransitionState2 = jest + const mockOnTransition1 = jest.fn().mockReturnValue({ runningVal: 'test1' }); + const mockOnTransition2 = jest .fn() .mockImplementation(() => Promise.resolve({ runningVal: 'test2' })); - const mockOnTransitionState3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); + const mockOnTransition3 = jest.fn().mockReturnValue({ runningVal: 'test3' }); const mockPostTransition = jest.fn(); - const contextData = { fixedVal: 'something' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData, - mockPostTransition - ); + const context = { fixedVal: 'something' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + mockPostTransition, + }); const updatedContext = await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalled(); + expect(mockOnTransition1).toHaveBeenCalled(); expect(mockPostTransition).toHaveBeenCalled(); - expect(mockOnTransitionState2).toHaveBeenCalled(); + expect(mockOnTransition2).toHaveBeenCalled(); expect(mockPostTransition).toHaveBeenCalled(); - expect(mockOnTransitionState3).toHaveBeenCalled(); + expect(mockOnTransition3).toHaveBeenCalled(); expect(updatedContext).toEqual( expect.objectContaining({ fixedVal: 'something', @@ -421,22 +507,22 @@ describe('handleState', () => { it('should execute postTransition correctly also when a transition throws', async () => { const error = new Error('Installation failed'); - const mockOnTransitionState1 = jest.fn().mockReturnValue({ result1: 'test' }); - const mockOnTransitionState2 = jest.fn().mockRejectedValue(error); - const mockOnTransitionState3 = jest.fn(); + const mockOnTransition1 = jest.fn().mockReturnValue({ result1: 'test' }); + const mockOnTransition2 = jest.fn().mockRejectedValue(error); + const mockOnTransition3 = jest.fn(); const mockPostTransition = jest.fn(); - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData, - mockPostTransition - ); + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + mockPostTransition, + }); const promise = handleState('state1', testDefinition, testDefinition.context); await expect(promise).rejects.toThrowError('Installation failed'); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(1); + expect(mockOnTransition1).toHaveBeenCalledTimes(1); expect(mockPostTransition).toHaveBeenCalledWith( expect.objectContaining({ result1: 'test', @@ -449,7 +535,7 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState2).toHaveBeenCalledTimes(1); + expect(mockOnTransition2).toHaveBeenCalledTimes(1); expect(mockPostTransition).toHaveBeenCalledWith( expect.objectContaining({ result1: 'test', @@ -460,26 +546,26 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState3).toHaveBeenCalledTimes(0); + expect(mockOnTransition3).toHaveBeenCalledTimes(0); }); it('should log a warning when postTransition exits with errors and continue executing the states', async () => { const error = new Error('Installation failed'); - const mockOnTransitionState1 = jest.fn().mockReturnValue({ result1: 'test' }); - const mockOnTransitionState2 = jest.fn(); - const mockOnTransitionState3 = jest.fn(); + const mockOnTransition1 = jest.fn().mockReturnValue({ result1: 'test' }); + const mockOnTransition2 = jest.fn(); + const mockOnTransition3 = jest.fn(); const mockPostTransition = jest.fn().mockRejectedValue(error); - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData, - mockPostTransition - ); + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + mockPostTransition, + }); const updatedContext = await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(1); + expect(mockOnTransition1).toHaveBeenCalledTimes(1); expect(mockPostTransition).toHaveBeenCalledWith( expect.objectContaining({ result1: 'test', @@ -490,8 +576,8 @@ describe('handleState', () => { }, }) ); - expect(mockOnTransitionState2).toHaveBeenCalledTimes(1); - expect(mockOnTransitionState3).toHaveBeenCalledTimes(1); + expect(mockOnTransition2).toHaveBeenCalledTimes(1); + expect(mockOnTransition3).toHaveBeenCalledTimes(1); expect(mockContract.logger?.warn).toHaveBeenCalledWith( 'Error during execution of post transition function: Installation failed' ); @@ -509,21 +595,21 @@ describe('handleState', () => { }); it('should exit and log a warning when the provided OnTransition is not a function', async () => { - const mockOnTransitionState1 = jest.fn().mockReturnValue({ result1: 'test' }); - const mockOnTransitionState2 = undefined; - const mockOnTransitionState3 = jest.fn(); - - const contextData = { testData: 'test' }; - const testDefinition = getTestDefinition( - mockOnTransitionState1, - mockOnTransitionState2, - mockOnTransitionState3, - contextData - ); + const mockOnTransition1 = jest.fn().mockReturnValue({ result1: 'test' }); + const mockOnTransition2 = undefined; + const mockOnTransition3 = jest.fn(); + + const context = { testData: 'test' }; + const testDefinition = getTestDefinition({ + mockOnTransition1, + mockOnTransition2, + mockOnTransition3, + context, + }); const updatedContext = await handleState('state1', testDefinition, testDefinition.context); - expect(mockOnTransitionState1).toHaveBeenCalledTimes(1); - expect(mockOnTransitionState3).toHaveBeenCalledTimes(0); + expect(mockOnTransition1).toHaveBeenCalledTimes(1); + expect(mockOnTransition3).toHaveBeenCalledTimes(0); expect(mockContract.logger?.warn).toHaveBeenCalledWith( 'Execution of state "state2" with status "failed": provided onTransition is not a valid function' ); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.ts b/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.ts index c70a99e272361..4817dccc300a3 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install_state_machine/state_machine.ts @@ -13,6 +13,7 @@ export interface State { onTransition: any; nextState?: string; currentStatus?: string; + onPreTransition?: any; onPostTransition?: any; } @@ -24,16 +25,19 @@ export type StateMachineStates = Record; * context: {}, * states: { * state1: { + * onPreTransition: onPreTransition, * onTransition: onState1Transition, * onPostTransition: onPostTransition, * nextState: 'state2', * }, * state2: { + * onPreTransition: onPreTransition, * onTransition: onState2Transition, * onPostTransition: onPostTransition,, * nextState: 'state3', * }, * state3: { + * onPreTransition: onPreTransition, * onTransition: onState3Transition, * onPostTransition: onPostTransition, * nextState: 'end', @@ -63,6 +67,10 @@ export async function handleState( let currentStatus = 'pending'; let stateResult; let updatedContext = { ...context }; + + // execute pre transition function, if available + await executePreTransition(logger, updatedContext, currentState); + if (typeof currentState.onTransition === 'function') { logger.debug( `Current state ${currentStateName}: running transition ${currentState.onTransition.name}` @@ -123,6 +131,9 @@ export async function handleState( } } +/* + * executePostTransition: function that gets executed after the execution of any step, when defined + */ async function executePostTransition( logger: Logger, updatedContext: StateContext, @@ -137,3 +148,24 @@ async function executePostTransition( } } } + +/* + * executePreTransition: function that gets executed before the execution of any step, when defined + */ +async function executePreTransition( + logger: Logger, + updatedContext: StateContext, + currentState: State +) { + if (typeof currentState.onPreTransition === 'function') { + try { + await currentState.onPreTransition.call(undefined, updatedContext); + logger.debug(`Executing pre transition function: ${currentState.onPreTransition.name}`); + } catch (error) { + logger.warn(`Error during execution of pre transition function: ${error.message}`); + + // bubble up the error; if something goes wrong in the precondition we want to see what happened + throw error; + } + } +} From 9293bc19179c62e004f982863d8cb96eb59b7a51 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Tue, 27 Aug 2024 10:39:12 +0200 Subject: [PATCH 22/38] [Security Solution] One Discover - Enable Security Solution Expandable Flyout in One Discover entities (#189633) >[!Note] > This Change is only applicable to Serverless Security Solution as of now. In follow-up PRs, support will be added to ESS as well based data-sources such as index or intergrations. ## Summary Resolves https://github.com/elastic/kibana/issues/189151 This PR is foundation for the work described in https://github.com/elastic/kibana/issues/186783. This just enables expandable flyout for entity details, which is currently only used in security solution, in discover as well. As a part of **One Discover** work, we need to make sure that cell rendering in Discover should behave exactly like it does in security solution. To enable this, a new `shared-browser` package `@kbn/security-solution-common` in `x-pack/packages/security-solution` has been created which can used to share components between `security solution` and `discover`. Below is the usage pattern ```mermaid flowchart TD disc-utils[@kbn/discover-utils] --> sscommon sscommon[@kbn/security-solution-common] --> ssplugin[security_solution] sscommon[@kbn/security-solution-common] --> discover[discover] disc-utils[@kbn/discover-utils] --> discover ``` ## Desk Testing Guide. 1. Enable Security profile in serverless by adding below to `kibana.yml` ```yaml discover.experimental.enabledProfiles: ['security-root-profile'] ``` 2. Load Some data 4. Navigate to discover and add `host.name` as one of the column. 5. Should open an expandable flyout as shown below. https://github.com/user-attachments/assets/92b84c89-8769-45dd-bf7e-a9fe527fdcf0 ## Code Review Guide Most of the changes in the PR are code-organization. There are NO changes in security solution but only the changes to import statements. You can focus regarding the changes in below packages: - x-pack/packages/security-solution/common - packages/kbn-discover-utils - packages/kbn-expandable-flyout --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 4 +- package.json | 1 + packages/kbn-discover-utils/index.ts | 1 + .../src/utils/get_field_value.test.ts | 33 ++++++++++ .../src/utils/get_field_value.ts | 14 ++++ .../kbn-discover-utils/src/utils/index.ts | 1 + .../kbn-expandable-flyout/__mocks__/index.tsx | 39 +++++++++++ packages/kbn-expandable-flyout/index.ts | 1 + .../kbn-expandable-flyout/src/index.test.tsx | 23 +++++++ packages/kbn-expandable-flyout/src/index.tsx | 4 +- .../src/with_provider.test.tsx | 29 ++++++++ .../src/with_provider.tsx | 25 +++++++ packages/kbn-unified-data-table/kibana.jsonc | 5 +- .../example_data_source_profile/profile.tsx | 8 +-- .../example_document_profile/profile.ts | 8 +-- .../example_root_pofile/profile.tsx | 1 + .../register_profile_providers.test.ts | 35 +++++++--- .../register_profile_providers.ts | 55 ++++++++-------- .../security/security_root_profile/index.ts | 9 +++ .../security_root_profile/profile.tsx | 38 +++++++++++ .../profile_providers/security/types.ts | 11 ++++ .../context_awareness/profile_service.ts | 12 ++++ src/plugins/discover/public/plugin.tsx | 4 +- src/plugins/discover/tsconfig.json | 7 +- tsconfig.base.json | 2 + .../security-solution/common/index.ts | 11 ++++ .../security-solution/common/jest.config.js | 12 ++++ .../security-solution/common/kibana.jsonc | 5 ++ .../security-solution/common/package.json | 8 +++ .../common/src/cells/renderers/discover.ts | 24 +++++++ .../common/src/cells/renderers/get.ts | 9 +++ .../src/cells/renderers/host/button.test.tsx | 30 +++++++++ .../src/cells/renderers/host/button.tsx | 27 ++++++++ .../common/src/cells/renderers/host/index.tsx | 9 +++ .../host/with_expandable_flyout.test.tsx | 54 +++++++++++++++ .../renderers/host/with_expandable_flyout.tsx | 66 +++++++++++++++++++ .../common/src/cells/renderers/index.ts | 8 +++ .../components/expandable_panel.stories.tsx | 0 .../components/expandable_panel.test.tsx | 8 +-- .../common}/components/expandable_panel.tsx | 4 +- .../common}/components/flyout_body.test.tsx | 0 .../flyout/common}/components/flyout_body.tsx | 0 .../components/flyout_error.stories.tsx | 0 .../common}/components/flyout_error.test.tsx | 2 +- .../common}/components/flyout_error.tsx | 6 +- .../common}/components/flyout_footer.test.tsx | 0 .../common}/components/flyout_footer.tsx | 0 .../common}/components/flyout_header.test.tsx | 0 .../common}/components/flyout_header.tsx | 0 .../components/flyout_header_tabs.test.tsx | 0 .../common}/components/flyout_header_tabs.tsx | 0 .../components/flyout_loading.stories.tsx | 0 .../components/flyout_loading.test.tsx | 2 +- .../common}/components/flyout_loading.tsx | 2 +- .../components/flyout_navigation.stories.tsx | 0 .../components/flyout_navigation.test.tsx | 50 ++++++++++---- .../common}/components/flyout_navigation.tsx | 10 +-- .../components/flyout_title.stories.tsx | 2 +- .../common}/components/flyout_title.test.tsx | 2 +- .../common}/components/flyout_title.tsx | 0 .../src/flyout/common/components/index.ts | 16 +++++ .../common/src/flyout/common}/test_ids.ts | 2 +- .../common/src/flyout/index.tsx | 10 +++ .../src/flyout/panels/host/right/index.tsx | 37 +++++++++++ .../common/src/flyout/panels/index.ts | 9 +++ .../common/src/flyout/panels/keys.ts | 8 +++ .../security-solution/common/tsconfig.json | 28 ++++++++ .../field_markdown_renderer/index.test.tsx | 14 +--- .../control_columns/row_action/index.test.tsx | 17 +++-- .../common/lib/kibana/kibana_react.mock.ts | 3 +- .../public/common/mock/expandable_flyout.tsx | 34 ++++++++++ .../index.test.tsx | 12 ++-- .../risk_summary_flyout/risk_summary.tsx | 2 +- .../alert_reason/alert_reason.tsx | 2 +- .../document_details/alert_reason/context.tsx | 3 +- .../document_details/isolate_host/content.tsx | 2 +- .../document_details/isolate_host/context.tsx | 3 +- .../document_details/isolate_host/header.tsx | 2 +- .../components/correlations_details.test.tsx | 2 +- ...correlations_details_alerts_table.test.tsx | 5 +- .../correlations_details_alerts_table.tsx | 2 +- .../left/components/entities_details.test.tsx | 2 +- .../left/components/host_details.test.tsx | 7 +- .../left/components/host_details.tsx | 2 +- .../left/components/investigation_guide.tsx | 2 +- .../components/prevalence_details.test.tsx | 5 +- .../related_alerts_by_ancestry.test.tsx | 2 +- ...lated_alerts_by_same_source_event.test.tsx | 2 +- .../related_alerts_by_session.test.tsx | 2 +- .../left/components/related_cases.test.tsx | 2 +- .../left/components/related_cases.tsx | 2 +- .../components/suppressed_alerts.test.tsx | 2 +- .../left/components/suppressed_alerts.tsx | 2 +- .../threat_intelligence_details.tsx | 2 +- .../document_details/left/components/tour.tsx | 2 +- .../left/components/user_details.test.tsx | 7 +- .../left/components/user_details.tsx | 2 +- .../flyout/document_details/left/content.tsx | 2 +- .../flyout/document_details/left/header.tsx | 2 +- .../flyout/document_details/left/test_ids.ts | 2 +- .../document_details/preview/footer.test.tsx | 5 +- .../document_details/preview/footer.tsx | 2 +- .../components/alert_description.test.tsx | 2 +- .../right/components/alert_header_title.tsx | 2 +- .../analyzer_preview_container.test.tsx | 2 +- .../components/analyzer_preview_container.tsx | 2 +- .../components/correlations_overview.test.tsx | 7 +- .../components/correlations_overview.tsx | 2 +- .../components/entities_overview.test.tsx | 2 +- .../right/components/entities_overview.tsx | 2 +- .../right/components/event_header_title.tsx | 2 +- .../highlighted_fields_cell.test.tsx | 5 +- .../components/host_entity_overview.test.tsx | 5 +- .../components/investigation_guide.test.tsx | 2 +- .../components/prevalence_overview.test.tsx | 7 +- .../right/components/prevalence_overview.tsx | 2 +- .../right/components/reason.test.tsx | 5 +- .../session_preview_container.test.tsx | 2 +- .../components/session_preview_container.tsx | 2 +- .../threat_intelligence_overview.test.tsx | 7 +- .../threat_intelligence_overview.tsx | 2 +- .../right/components/tour.tsx | 2 +- .../components/user_entity_overview.test.tsx | 10 +-- .../flyout/document_details/right/content.tsx | 2 +- .../flyout/document_details/right/header.tsx | 3 +- .../document_details/right/navigation.tsx | 2 +- .../rule_overview/components/footer.tsx | 2 +- .../components/rule_overview.tsx | 3 +- .../rule_overview/context.tsx | 2 +- .../document_details/rule_overview/index.tsx | 2 +- .../document_details/shared/context.tsx | 3 +- .../shared/utils/tour_step_config.tsx | 2 +- .../host_preview/footer.test.tsx | 5 +- .../entity_details/host_preview/footer.tsx | 2 +- .../entity_details/host_right/content.tsx | 2 +- .../entity_details/host_right/header.tsx | 3 +- .../entity_details/host_right/index.tsx | 3 +- .../left_panel/left_panel_content.tsx | 2 +- .../left_panel/left_panel_header.tsx | 2 +- .../user_details_left/index.tsx | 2 +- .../user_details_left/tabs/asset_document.tsx | 2 +- .../user_preview/footer.test.tsx | 5 +- .../entity_details/user_preview/footer.tsx | 2 +- .../components/managed_user_accordion.tsx | 3 +- .../entity_details/user_right/content.tsx | 2 +- .../entity_details/user_right/header.tsx | 3 +- .../entity_details/user_right/index.tsx | 3 +- .../public/flyout/network_details/content.tsx | 2 +- .../public/flyout/network_details/header.tsx | 3 +- .../components/alert_preview_button.test.tsx | 3 + .../components/formatted_ip/index.test.tsx | 14 ++-- .../components/timeline/body/index.test.tsx | 13 ++-- .../body/renderers/host_name.test.tsx | 20 +++--- .../body/renderers/user_name.test.tsx | 19 +++--- .../query_tab_unified_components.test.tsx | 21 +++--- .../plugins/security_solution/tsconfig.json | 7 +- .../translations/translations/fr-FR.json | 17 +++-- .../translations/translations/ja-JP.json | 16 ++--- .../translations/translations/zh-CN.json | 16 ++--- yarn.lock | 4 ++ 160 files changed, 966 insertions(+), 317 deletions(-) create mode 100644 packages/kbn-discover-utils/src/utils/get_field_value.test.ts create mode 100644 packages/kbn-discover-utils/src/utils/get_field_value.ts create mode 100644 packages/kbn-expandable-flyout/__mocks__/index.tsx create mode 100644 packages/kbn-expandable-flyout/src/with_provider.test.tsx create mode 100644 packages/kbn-expandable-flyout/src/with_provider.tsx create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/security/types.ts create mode 100644 x-pack/packages/security-solution/common/index.ts create mode 100644 x-pack/packages/security-solution/common/jest.config.js create mode 100644 x-pack/packages/security-solution/common/kibana.jsonc create mode 100644 x-pack/packages/security-solution/common/package.json create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/discover.ts create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/get.ts create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/host/button.test.tsx create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/host/index.tsx create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.test.tsx create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.tsx create mode 100644 x-pack/packages/security-solution/common/src/cells/renderers/index.ts rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/expandable_panel.stories.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/expandable_panel.test.tsx (97%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/expandable_panel.tsx (97%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_body.test.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_body.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_error.stories.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_error.test.tsx (94%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_error.tsx (84%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_footer.test.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_footer.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_header.test.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_header.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_header_tabs.test.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_header_tabs.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_loading.stories.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_loading.test.tsx (94%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_loading.tsx (94%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_navigation.stories.tsx (100%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_navigation.test.tsx (78%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_navigation.tsx (91%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_title.stories.tsx (98%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_title.test.tsx (98%) rename x-pack/{plugins/security_solution/public/flyout/shared => packages/security-solution/common/src/flyout/common}/components/flyout_title.tsx (100%) create mode 100644 x-pack/packages/security-solution/common/src/flyout/common/components/index.ts rename x-pack/{plugins/security_solution/public/flyout/shared/components => packages/security-solution/common/src/flyout/common}/test_ids.ts (97%) create mode 100644 x-pack/packages/security-solution/common/src/flyout/index.tsx create mode 100644 x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx create mode 100644 x-pack/packages/security-solution/common/src/flyout/panels/index.ts create mode 100644 x-pack/packages/security-solution/common/src/flyout/panels/keys.ts create mode 100644 x-pack/packages/security-solution/common/tsconfig.json create mode 100644 x-pack/plugins/security_solution/public/common/mock/expandable_flyout.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 450fbb023af95..b74db49fc30ea 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -762,6 +762,7 @@ x-pack/packages/security/plugin_types_common @elastic/kibana-security x-pack/packages/security/plugin_types_public @elastic/kibana-security x-pack/packages/security/plugin_types_server @elastic/kibana-security x-pack/packages/security/role_management_model @elastic/kibana-security +x-pack/packages/security-solution/common @elastic/security-threat-hunting-investigations x-pack/packages/security-solution/distribution_bar @elastic/kibana-cloud-security-posture x-pack/plugins/security_solution_ess @elastic/security-solution x-pack/packages/security-solution/features @elastic/security-threat-hunting-explore @@ -931,7 +932,7 @@ test/plugin_functional/plugins/ui_settings_plugin @elastic/kibana-core packages/kbn-ui-shared-deps-npm @elastic/kibana-operations packages/kbn-ui-shared-deps-src @elastic/kibana-operations packages/kbn-ui-theme @elastic/kibana-operations -packages/kbn-unified-data-table @elastic/kibana-data-discovery +packages/kbn-unified-data-table @elastic/kibana-data-discovery @elastic/security-threat-hunting-investigations packages/kbn-unified-doc-viewer @elastic/kibana-data-discovery examples/unified_doc_viewer @elastic/kibana-core src/plugins/unified_doc_viewer @elastic/kibana-data-discovery @@ -1036,6 +1037,7 @@ packages/kbn-zod-helpers @elastic/security-detection-rule-management /x-pack/test_serverless/functional/test_suites/common/examples/search_examples @elastic/kibana-data-discovery /x-pack/test_serverless/functional/test_suites/common/examples/unified_field_list_examples @elastic/kibana-data-discovery /x-pack/test_serverless/functional/test_suites/common/management/data_views @elastic/kibana-data-discovery +src/plugins/discover/public/context_awareness/profile_providers/security @elastic/kibana-data-discovery @elastic/security-threat-hunting-investigations # Visualizations /src/plugins/visualize/ @elastic/kibana-visualizations diff --git a/package.json b/package.json index c07597726ca47..78d2e97408fa0 100644 --- a/package.json +++ b/package.json @@ -778,6 +778,7 @@ "@kbn/security-plugin-types-public": "link:x-pack/packages/security/plugin_types_public", "@kbn/security-plugin-types-server": "link:x-pack/packages/security/plugin_types_server", "@kbn/security-role-management-model": "link:x-pack/packages/security/role_management_model", + "@kbn/security-solution-common": "link:x-pack/packages/security-solution/common", "@kbn/security-solution-distribution-bar": "link:x-pack/packages/security-solution/distribution_bar", "@kbn/security-solution-ess": "link:x-pack/plugins/security_solution_ess", "@kbn/security-solution-features": "link:x-pack/packages/security-solution/features", diff --git a/packages/kbn-discover-utils/index.ts b/packages/kbn-discover-utils/index.ts index 656d3e1cf0fec..d494955d8d644 100644 --- a/packages/kbn-discover-utils/index.ts +++ b/packages/kbn-discover-utils/index.ts @@ -50,6 +50,7 @@ export { getLogLevelCoalescedValueLabel, LogLevelCoalescedValue, LogLevelBadge, + getFieldValue, } from './src'; export type { LogsContextService } from './src'; diff --git a/packages/kbn-discover-utils/src/utils/get_field_value.test.ts b/packages/kbn-discover-utils/src/utils/get_field_value.test.ts new file mode 100644 index 0000000000000..fcdc151f54947 --- /dev/null +++ b/packages/kbn-discover-utils/src/utils/get_field_value.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { DataTableRecord } from '../types'; +import { getFieldValue } from './get_field_value'; + +const dataTableRecord: DataTableRecord = { + id: '1', + raw: {}, + flattened: { + 'field1.value': 'value1', + 'field2.value': ['value2'], + }, +}; + +describe('getFieldValue', () => { + it('should return the value of field correctly', () => { + expect(getFieldValue(dataTableRecord, 'field1.value')).toBe('value1'); + }); + + it('should return the first value of field correctly if field has a value of Array type', () => { + expect(getFieldValue(dataTableRecord, 'field2.value')).toBe('value2'); + }); + + it('should return undefined when field is not available', () => { + expect(getFieldValue(dataTableRecord, 'field3.value')).toBeUndefined(); + }); +}); diff --git a/packages/kbn-discover-utils/src/utils/get_field_value.ts b/packages/kbn-discover-utils/src/utils/get_field_value.ts new file mode 100644 index 0000000000000..043b5f2458a7a --- /dev/null +++ b/packages/kbn-discover-utils/src/utils/get_field_value.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. + */ + +import { DataTableRecord } from '../types'; + +export const getFieldValue = (record: DataTableRecord, field: string) => { + const value = record.flattened[field]; + return Array.isArray(value) ? value[0] : value; +}; diff --git a/packages/kbn-discover-utils/src/utils/index.ts b/packages/kbn-discover-utils/src/utils/index.ts index fd368beda5d7c..6c719f74dfa7a 100644 --- a/packages/kbn-discover-utils/src/utils/index.ts +++ b/packages/kbn-discover-utils/src/utils/index.ts @@ -15,5 +15,6 @@ export * from './get_log_document_overview'; export * from './get_message_field_with_fallbacks'; export * from './get_should_show_field_handler'; export * from './nested_fields'; +export * from './get_field_value'; export * from './calc_field_counts'; export { isLegacyTableEnabled } from './is_legacy_table_enabled'; diff --git a/packages/kbn-expandable-flyout/__mocks__/index.tsx b/packages/kbn-expandable-flyout/__mocks__/index.tsx new file mode 100644 index 0000000000000..1b35419219fbb --- /dev/null +++ b/packages/kbn-expandable-flyout/__mocks__/index.tsx @@ -0,0 +1,39 @@ +/* + * 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 React from 'react'; + +export const useExpandableFlyoutApi = jest.fn(() => ({ + openFlyout: jest.fn(), + closeFlyout: jest.fn(), + openPanels: jest.fn(), + openRightPanel: jest.fn(), + openLeftPanel: jest.fn(), + openPreviewPanel: jest.fn(), + closeRightPanel: jest.fn(), + closeLeftPanel: jest.fn(), + closePreviewPanel: jest.fn(), + closePanels: jest.fn(), + previousPreviewPanel: jest.fn(), +})); + +export const useExpandableFlyoutState = jest.fn(); + +export const ExpandableFlyoutProvider = jest.fn(({ children }: React.PropsWithChildren<{}>) => { + return <>{children}; +}); + +export const withExpandableFlyoutProvider = ( + Component: React.ComponentType +) => { + return (props: T) => { + return ; + }; +}; + +export const ExpandableFlyout = jest.fn(); diff --git a/packages/kbn-expandable-flyout/index.ts b/packages/kbn-expandable-flyout/index.ts index e5eaae99c26f8..00f9b1521cc4d 100644 --- a/packages/kbn-expandable-flyout/index.ts +++ b/packages/kbn-expandable-flyout/index.ts @@ -14,6 +14,7 @@ export { useExpandableFlyoutState } from './src/hooks/use_expandable_flyout_stat export { type FlyoutState as ExpandableFlyoutState } from './src/state'; export { ExpandableFlyoutProvider } from './src/provider'; +export { withExpandableFlyoutProvider } from './src/with_provider'; export type { ExpandableFlyoutProps } from './src'; export type { FlyoutPanelProps, PanelPath, ExpandableFlyoutApi } from './src/types'; diff --git a/packages/kbn-expandable-flyout/src/index.test.tsx b/packages/kbn-expandable-flyout/src/index.test.tsx index d08a78c706781..2235cbd5d408b 100644 --- a/packages/kbn-expandable-flyout/src/index.test.tsx +++ b/packages/kbn-expandable-flyout/src/index.test.tsx @@ -110,4 +110,27 @@ describe('ExpandableFlyout', () => { expect(getByTestId(PREVIEW_SECTION_TEST_ID)).toBeInTheDocument(); }); + + it('should not render flyout when right has value but does not matches registered panels', () => { + const state = { + byId: { + [id]: { + right: { + id: 'key1', + }, + left: undefined, + preview: undefined, + }, + }, + }; + + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('my-test-flyout')).toBeNull(); + expect(queryByTestId(RIGHT_SECTION_TEST_ID)).toBeNull(); + }); }); diff --git a/packages/kbn-expandable-flyout/src/index.tsx b/packages/kbn-expandable-flyout/src/index.tsx index ba11b597e0b06..a112187bd733b 100644 --- a/packages/kbn-expandable-flyout/src/index.tsx +++ b/packages/kbn-expandable-flyout/src/index.tsx @@ -86,7 +86,8 @@ export const ExpandableFlyout: React.FC = ({ showPreview, }); - const hideFlyout = !left && !right && !preview?.length; + const hideFlyout = !(left && leftSection) && !(right && rightSection) && !preview?.length; + if (hideFlyout) { return null; } @@ -94,6 +95,7 @@ export const ExpandableFlyout: React.FC = ({ return ( { diff --git a/packages/kbn-expandable-flyout/src/with_provider.test.tsx b/packages/kbn-expandable-flyout/src/with_provider.test.tsx new file mode 100644 index 0000000000000..e262157048778 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/with_provider.test.tsx @@ -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 { render } from '@testing-library/react'; +import { useExpandableFlyoutApi } from './hooks/use_expandable_flyout_api'; +import React from 'react'; +import { withExpandableFlyoutProvider } from './with_provider'; + +const TestComponent = () => { + useExpandableFlyoutApi(); + + return
; +}; + +describe('withExpandableFlyoutProvider', () => { + it('should throw when rendered without Expandable Provider', () => { + expect(() => render()).toThrow(); + }); + + it('should not throw when rendered with Expandable Provider', () => { + const TestComponentWithProvider = withExpandableFlyoutProvider(TestComponent); + expect(() => render()).not.toThrow(); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/with_provider.tsx b/packages/kbn-expandable-flyout/src/with_provider.tsx new file mode 100644 index 0000000000000..a12b46a6405d0 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/with_provider.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 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 React from 'react'; +import { ComponentType } from 'react'; +import { ExpandableFlyoutContextProviderProps } from './context'; +import { ExpandableFlyoutProvider } from './provider'; + +export const withExpandableFlyoutProvider = ( + Component: ComponentType, + expandableProviderProps?: ExpandableFlyoutContextProviderProps +) => { + return (props: Props) => { + return ( + + + + ); + }; +}; diff --git a/packages/kbn-unified-data-table/kibana.jsonc b/packages/kbn-unified-data-table/kibana.jsonc index 3fe1b76b931c3..b80f8b6a55596 100644 --- a/packages/kbn-unified-data-table/kibana.jsonc +++ b/packages/kbn-unified-data-table/kibana.jsonc @@ -2,5 +2,8 @@ "type": "shared-browser", "id": "@kbn/unified-data-table", "description": "Contains functionality for the unified data table which can be integrated into apps", - "owner": "@elastic/kibana-data-discovery" + "owner": [ + "@elastic/kibana-data-discovery", + "@elastic/security-threat-hunting-investigations" + ] } diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx index 747bada5b0284..2d30aeee2e2c3 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx @@ -7,7 +7,7 @@ */ import { EuiBadge } from '@elastic/eui'; -import type { DataTableRecord } from '@kbn/discover-utils'; +import { getFieldValue } from '@kbn/discover-utils'; import type { RowControlColumn } from '@kbn/unified-data-table'; import { isOfAggregateQueryType } from '@kbn/es-query'; import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; @@ -19,6 +19,7 @@ import { DataSourceCategory, DataSourceProfileProvider } from '../../profiles'; export const exampleDataSourceProfileProvider: DataSourceProfileProvider = { profileId: 'example-data-source-profile', + isExperimental: true, profile: { getCellRenderers: (prev) => () => ({ ...prev(), @@ -137,8 +138,3 @@ export const exampleDataSourceProfileProvider: DataSourceProfileProvider = { }; }, }; - -const getFieldValue = (record: DataTableRecord, field: string) => { - const value = record.flattened[field]; - return Array.isArray(value) ? value[0] : value; -}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts index 9739430e08000..61045fe37c342 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts @@ -6,11 +6,12 @@ * Side Public License, v 1. */ -import type { DataTableRecord } from '@kbn/discover-utils'; +import { getFieldValue } from '@kbn/discover-utils'; import { DocumentProfileProvider, DocumentType } from '../../profiles'; export const exampleDocumentProfileProvider: DocumentProfileProvider = { profileId: 'example-document-profile', + isExperimental: true, profile: {}, resolve: (params) => { if (getFieldValue(params.record, 'data_stream.type') !== 'example') { @@ -25,8 +26,3 @@ export const exampleDocumentProfileProvider: DocumentProfileProvider = { }; }, }; - -const getFieldValue = (record: DataTableRecord, field: string) => { - const value = record.flattened[field]; - return Array.isArray(value) ? value[0] : value; -}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx index 389059c518217..4d00318018a48 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx @@ -13,6 +13,7 @@ import { RootProfileProvider, SolutionType } from '../../profiles'; export const exampleRootProfileProvider: RootProfileProvider = { profileId: 'example-root-profile', + isExperimental: true, profile: { getCellRenderers: (prev) => () => ({ ...prev(), diff --git a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts index 78048cdcbad60..de404317b1a39 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts +++ b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts @@ -12,34 +12,51 @@ import { exampleDataSourceProfileProvider } from './example_data_source_profile' import { exampleDocumentProfileProvider } from './example_document_profile'; import { exampleRootProfileProvider } from './example_root_pofile'; import { - registerEnabledProfileProviders, registerProfileProviders, + registerEnabledProfileProviders, } from './register_profile_providers'; describe('registerEnabledProfileProviders', () => { - it('should register enabled profile providers', async () => { + it('should register all profile providers', async () => { const { rootProfileServiceMock, rootProfileProviderMock } = createContextAwarenessMocks({ shouldRegisterProviders: false, }); registerEnabledProfileProviders({ profileService: rootProfileServiceMock, - availableProviders: [rootProfileProviderMock], - enabledProfileIds: ['root-profile'], + providers: [rootProfileProviderMock], + enabledExperimentalProfileIds: [], }); const context = await rootProfileServiceMock.resolve({ solutionNavId: null }); expect(rootProfileServiceMock.getProfile(context)).toBe(rootProfileProviderMock.profile); }); - it('should not register disabled profile providers', async () => { + it('should not register experimental profile providers by default', async () => { + const { rootProfileServiceMock } = createContextAwarenessMocks({ + shouldRegisterProviders: false, + }); + + registerEnabledProfileProviders({ + profileService: rootProfileServiceMock, + providers: [exampleRootProfileProvider], + enabledExperimentalProfileIds: [], + }); + const context = await rootProfileServiceMock.resolve({ solutionNavId: null }); + expect(rootProfileServiceMock.getProfile(context)).not.toBe(exampleRootProfileProvider.profile); + expect(rootProfileServiceMock.getProfile(context)).toMatchObject({}); + }); + + it('should register experimental profile providers when enabled by config', async () => { const { rootProfileServiceMock, rootProfileProviderMock } = createContextAwarenessMocks({ shouldRegisterProviders: false, }); + registerEnabledProfileProviders({ profileService: rootProfileServiceMock, - availableProviders: [rootProfileProviderMock], - enabledProfileIds: [], + providers: [exampleRootProfileProvider], + enabledExperimentalProfileIds: [exampleRootProfileProvider.profileId], }); const context = await rootProfileServiceMock.resolve({ solutionNavId: null }); + expect(rootProfileServiceMock.getProfile(context)).toBe(exampleRootProfileProvider.profile); expect(rootProfileServiceMock.getProfile(context)).not.toBe(rootProfileProviderMock.profile); }); }); @@ -54,7 +71,7 @@ describe('registerProfileProviders', () => { rootProfileService: rootProfileServiceMock, dataSourceProfileService: dataSourceProfileServiceMock, documentProfileService: documentProfileServiceMock, - experimentalProfileIds: [ + enabledExperimentalProfileIds: [ exampleRootProfileProvider.profileId, exampleDataSourceProfileProvider.profileId, exampleDocumentProfileProvider.profileId, @@ -93,7 +110,7 @@ describe('registerProfileProviders', () => { rootProfileService: rootProfileServiceMock, dataSourceProfileService: dataSourceProfileServiceMock, documentProfileService: documentProfileServiceMock, - experimentalProfileIds: [], + enabledExperimentalProfileIds: [], }); const rootContext = await rootProfileServiceMock.resolve({ solutionNavId: null }); const dataSourceContext = await dataSourceProfileServiceMock.resolve({ diff --git a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts index 22ed673cd9558..ffbad9bfe6f71 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts +++ b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts @@ -6,11 +6,9 @@ * Side Public License, v 1. */ -import { uniq } from 'lodash'; import type { DataSourceProfileService, DocumentProfileService, - RootProfileProvider, RootProfileService, } from '../profiles'; import type { BaseProfileProvider, BaseProfileService } from '../profile_service'; @@ -19,6 +17,7 @@ import { exampleDocumentProfileProvider } from './example_document_profile'; import { exampleRootProfileProvider } from './example_root_pofile'; import { createLogsDataSourceProfileProviders } from './logs_data_source_profile'; import { createLogDocumentProfileProvider } from './log_document_profile'; +import { createSecurityRootProfileProvider } from './security/security_root_profile'; import { createProfileProviderServices, ProfileProviderServices, @@ -28,40 +27,37 @@ export const registerProfileProviders = ({ rootProfileService, dataSourceProfileService, documentProfileService, - experimentalProfileIds, + enabledExperimentalProfileIds, }: { rootProfileService: RootProfileService; dataSourceProfileService: DataSourceProfileService; documentProfileService: DocumentProfileService; - experimentalProfileIds: string[]; + /** + * List of experimental profile Ids which are enabled in kibana config. + * */ + enabledExperimentalProfileIds: string[]; }) => { const providerServices = createProfileProviderServices(); const rootProfileProviders = createRootProfileProviders(providerServices); const dataSourceProfileProviders = createDataSourceProfileProviders(providerServices); const documentProfileProviders = createDocumentProfileProviders(providerServices); - const enabledProfileIds = uniq([ - ...extractProfileIds(rootProfileProviders), - ...extractProfileIds(dataSourceProfileProviders), - ...extractProfileIds(documentProfileProviders), - ...experimentalProfileIds, - ]); registerEnabledProfileProviders({ profileService: rootProfileService, - availableProviders: [exampleRootProfileProvider, ...rootProfileProviders], - enabledProfileIds, + providers: [...rootProfileProviders], + enabledExperimentalProfileIds, }); registerEnabledProfileProviders({ profileService: dataSourceProfileService, - availableProviders: [exampleDataSourceProfileProvider, ...dataSourceProfileProviders], - enabledProfileIds, + providers: [...dataSourceProfileProviders], + enabledExperimentalProfileIds, }); registerEnabledProfileProviders({ profileService: documentProfileService, - availableProviders: [exampleDocumentProfileProvider, ...documentProfileProviders], - enabledProfileIds, + providers: [...documentProfileProviders], + enabledExperimentalProfileIds, }); }; @@ -70,30 +66,37 @@ export const registerEnabledProfileProviders = < TService extends BaseProfileService >({ profileService, - availableProviders, - enabledProfileIds, + providers: availableProviders, + enabledExperimentalProfileIds = [], }: { profileService: TService; - availableProviders: TProvider[]; - enabledProfileIds: string[]; + providers: TProvider[]; + /** + * List of experimental profile Ids which are enabled in kibana config. + * */ + enabledExperimentalProfileIds?: string[]; }) => { for (const provider of availableProviders) { - if (enabledProfileIds.includes(provider.profileId)) { + const isProfileExperimental = provider.isExperimental ?? false; + const isProfileEnabled = + enabledExperimentalProfileIds.includes(provider.profileId) || !isProfileExperimental; + if (isProfileEnabled) { profileService.registerProvider(provider); } } }; -const extractProfileIds = (providers: Array>) => - providers.map(({ profileId }) => profileId); - -const createRootProfileProviders = (_providerServices: ProfileProviderServices) => - [] as RootProfileProvider[]; +const createRootProfileProviders = (_providerServices: ProfileProviderServices) => [ + exampleRootProfileProvider, + createSecurityRootProfileProvider(_providerServices), +]; const createDataSourceProfileProviders = (providerServices: ProfileProviderServices) => [ + exampleDataSourceProfileProvider, ...createLogsDataSourceProfileProviders(providerServices), ]; const createDocumentProfileProviders = (providerServices: ProfileProviderServices) => [ + exampleDocumentProfileProvider, createLogDocumentProfileProvider(providerServices), ]; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/index.ts new file mode 100644 index 0000000000000..b6bf175abed4d --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/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 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 { createSecurityRootProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx new file mode 100644 index 0000000000000..1bd58e361d88b --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx @@ -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 React from 'react'; +import { getDiscoverCellRenderer } from '@kbn/security-solution-common'; +import { RootProfileProvider, SolutionType } from '../../../profiles'; +import { ProfileProviderServices } from '../../profile_provider_services'; +import { SecurityProfileProviderFactory } from '../types'; + +export const createSecurityRootProfileProvider: SecurityProfileProviderFactory< + RootProfileProvider +> = (services: ProfileProviderServices) => ({ + profileId: 'security-root-profile', + isExperimental: true, + profile: { + getCellRenderers: (prev) => () => ({ + ...prev(), + 'host.name': (props) => { + const CellRenderer = getDiscoverCellRenderer({ + fieldName: 'host.name', + }); + return ; + }, + }), + }, + resolve: (params) => { + if (params.solutionNavId === SolutionType.Security) { + return { isMatch: true, context: { solutionType: SolutionType.Security } }; + } + + return { isMatch: false }; + }, +}); diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/types.ts b/src/plugins/discover/public/context_awareness/profile_providers/security/types.ts new file mode 100644 index 0000000000000..f04ec6f00efb1 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/security/types.ts @@ -0,0 +1,11 @@ +/* + * 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 { ProfileProviderServices } from '../profile_provider_services'; + +export type SecurityProfileProviderFactory = (services: ProfileProviderServices) => T; diff --git a/src/plugins/discover/public/context_awareness/profile_service.ts b/src/plugins/discover/public/context_awareness/profile_service.ts index efc143e222414..ac4f4eacee42c 100644 --- a/src/plugins/discover/public/context_awareness/profile_service.ts +++ b/src/plugins/discover/public/context_awareness/profile_service.ts @@ -20,6 +20,18 @@ export type ContextWithProfileId = TContext & { profileId: string }; export interface BaseProfileProvider { profileId: string; profile: ComposableProfile; + /** + * isExperimental Flag can be used for any profile which is under development and should not be enabled by default. + * + * Experimental profiles can still be enabled in kibana config with option `discover.experimental.enabledProfiles` as shown in example below: + * + * ```yaml + * discover.experimental.enabledProfiles: + * - example-root-profile + * - example-data-source-profile + * ``` + */ + isExperimental?: boolean; } export interface ProfileProvider diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index d81bacb958d38..61a205be2cff5 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -306,13 +306,13 @@ export class DiscoverPlugin const rootProfileService = new RootProfileService(); const dataSourceProfileService = new DataSourceProfileService(); const documentProfileService = new DocumentProfileService(); - const experimentalProfileIds = this.experimentalFeatures.enabledProfiles ?? []; + const enabledExperimentalProfileIds = this.experimentalFeatures.enabledProfiles ?? []; registerProfileProviders({ rootProfileService, dataSourceProfileService, documentProfileService, - experimentalProfileIds, + enabledExperimentalProfileIds, }); return { rootProfileService, dataSourceProfileService, documentProfileService }; diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index 526b3ea6ddf3c..a363981a5d731 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -94,7 +94,10 @@ "@kbn/search-types", "@kbn/presentation-containers", "@kbn/observability-ai-assistant-plugin", - "@kbn/fields-metadata-plugin" + "@kbn/fields-metadata-plugin", + "@kbn/security-solution-common" ], - "exclude": ["target/**/*"] + "exclude": [ + "target/**/*" + ] } diff --git a/tsconfig.base.json b/tsconfig.base.json index 846a51191ab72..d6b0733743929 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1518,6 +1518,8 @@ "@kbn/security-plugin-types-server/*": ["x-pack/packages/security/plugin_types_server/*"], "@kbn/security-role-management-model": ["x-pack/packages/security/role_management_model"], "@kbn/security-role-management-model/*": ["x-pack/packages/security/role_management_model/*"], + "@kbn/security-solution-common": ["x-pack/packages/security-solution/common"], + "@kbn/security-solution-common/*": ["x-pack/packages/security-solution/common/*"], "@kbn/security-solution-distribution-bar": ["x-pack/packages/security-solution/distribution_bar"], "@kbn/security-solution-distribution-bar/*": ["x-pack/packages/security-solution/distribution_bar/*"], "@kbn/security-solution-ess": ["x-pack/plugins/security_solution_ess"], diff --git a/x-pack/packages/security-solution/common/index.ts b/x-pack/packages/security-solution/common/index.ts new file mode 100644 index 0000000000000..ba5d797648f13 --- /dev/null +++ b/x-pack/packages/security-solution/common/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { HostDetailsButton } from './src/cells/renderers/host'; + +export * from './src/flyout'; +export * from './src/cells/renderers'; diff --git a/x-pack/packages/security-solution/common/jest.config.js b/x-pack/packages/security-solution/common/jest.config.js new file mode 100644 index 0000000000000..7047e229df092 --- /dev/null +++ b/x-pack/packages/security-solution/common/jest.config.js @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/security-solution/common'], +}; diff --git a/x-pack/packages/security-solution/common/kibana.jsonc b/x-pack/packages/security-solution/common/kibana.jsonc new file mode 100644 index 0000000000000..708feab435425 --- /dev/null +++ b/x-pack/packages/security-solution/common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-browser", + "id": "@kbn/security-solution-common", + "owner": "@elastic/security-threat-hunting-investigations" +} diff --git a/x-pack/packages/security-solution/common/package.json b/x-pack/packages/security-solution/common/package.json new file mode 100644 index 0000000000000..ce355e927c3df --- /dev/null +++ b/x-pack/packages/security-solution/common/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/security-solution-common", + "version": "1.0.0", + "description": "security solution common components which can be used in multiple plugins such as custom discover and timeline", + "license": "Elastic License 2.0", + "private": true, + "sideEffects": false +} \ No newline at end of file diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/discover.ts b/x-pack/packages/security-solution/common/src/cells/renderers/discover.ts new file mode 100644 index 0000000000000..8d0393a3c6f2b --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/discover.ts @@ -0,0 +1,24 @@ +/* + * 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 { DataGridCellValueElementProps } from '@kbn/unified-data-table'; +import { ComponentType, PropsWithChildren } from 'react'; +import { HostCellWithFlyoutRenderer } from './host'; + +export type DiscoverCellRenderer = ComponentType>; + +const RENDERERS: Record = { + 'host.name': HostCellWithFlyoutRenderer, +}; + +interface GetRendererArgs { + fieldName: string; +} + +export const getDiscoverCellRenderer = ({ fieldName }: GetRendererArgs) => { + return RENDERERS[fieldName]; +}; diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/get.ts b/x-pack/packages/security-solution/common/src/cells/renderers/get.ts new file mode 100644 index 0000000000000..3102c520e31db --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/get.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 { getDiscoverCellRenderer } from './discover'; +export type { DiscoverCellRenderer } from './discover'; diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/host/button.test.tsx b/x-pack/packages/security-solution/common/src/cells/renderers/host/button.test.tsx new file mode 100644 index 0000000000000..d49af3ed50518 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/host/button.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { HostDetailsButton } from './button'; +import { render, screen } from '@testing-library/react'; + +const onClickMock = jest.fn(); +const TestComponent = () => { + return {'Test'}; +}; + +describe('Host Button', () => { + it('should render as button with link formatting', () => { + render(); + expect(screen.getByTestId('host-details-button')).toBeVisible(); + expect(screen.getByTestId('host-details-button')).toHaveAttribute('type', 'button'); + expect(screen.getByTestId('host-details-button')).toHaveClass('euiLink'); + }); + + it('should perform onClick Correctly', () => { + render(); + screen.getByTestId('host-details-button').click(); + expect(onClickMock).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx b/x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx new file mode 100644 index 0000000000000..b478ee17bf9d4 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx @@ -0,0 +1,27 @@ +/* + * 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, { SyntheticEvent } from 'react'; +import { EuiLink } from '@elastic/eui'; + +interface HostDetailsButtonProps { + children?: React.ReactNode; + onClick?: (e: SyntheticEvent) => void; + title?: string; +} + +export const HostDetailsButton: React.FC = ({ + children, + onClick, + title, +}) => { + return ( + + {children} + + ); +}; diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/host/index.tsx b/x-pack/packages/security-solution/common/src/cells/renderers/host/index.tsx new file mode 100644 index 0000000000000..a39397b233d60 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/host/index.tsx @@ -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 './button'; +export * from './with_expandable_flyout'; diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.test.tsx b/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.test.tsx new file mode 100644 index 0000000000000..0568c656cdbe5 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.test.tsx @@ -0,0 +1,54 @@ +/* + * 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 { + HostCellWithFlyoutRenderer, + HostCellWithFlyoutRendererProps, +} from './with_expandable_flyout'; +import React from 'react'; +import { render, screen } from '@testing-library/react'; + +const renderTestComponents = (props?: Partial) => { + const finalProps: HostCellWithFlyoutRendererProps = { + rowIndex: 0, + columnId: 'test', + setCellProps: jest.fn(), + isExpandable: false, + isExpanded: true, + isDetails: false, + colIndex: 0, + fieldFormats: {} as HostCellWithFlyoutRendererProps['fieldFormats'], + dataView: {} as HostCellWithFlyoutRendererProps['dataView'], + closePopover: jest.fn(), + row: { + id: '1', + raw: { + _source: { + host: { + name: 'test-host-name', + }, + }, + }, + flattened: { + 'host.name': 'test-host-name', + }, + }, + ...props, + }; + return render(); +}; + +describe('With Expandable Flyout', () => { + it('should open Expandable Flyout on Click', () => { + renderTestComponents(); + + expect(screen.getByTestId('host-details-button')).toBeVisible(); + screen.getByTestId('host-details-button').click(); + expect(screen.getByTestId('host-name-flyout')).toBeVisible(); + expect(screen.getByText('Host Flyout Header - test-host-name')).toBeVisible(); + }); +}); diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.tsx b/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.tsx new file mode 100644 index 0000000000000..f870fd9f7d04e --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/host/with_expandable_flyout.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { getFieldValue } from '@kbn/discover-utils'; +import type { PropsWithChildren } from 'react'; +import type { DataGridCellValueElementProps } from '@kbn/unified-data-table'; +import { + ExpandableFlyout, + type ExpandableFlyoutProps, + useExpandableFlyoutApi, + withExpandableFlyoutProvider, +} from '@kbn/expandable-flyout'; +import { HostRightPanel, HostRightPanelProps } from '../../../flyout/panels'; +import { HostDetailsButton } from './button'; + +export type HostCellWithFlyoutRendererProps = PropsWithChildren; + +const HostCellWithFlyoutRendererComp = React.memo(function HostCellWithFlyoutRendererComp( + props: HostCellWithFlyoutRendererProps +) { + const hostName = getFieldValue(props.row, 'host.name'); + + const { openFlyout } = useExpandableFlyoutApi(); + + const onClick = useCallback(() => { + openFlyout({ + right: { + id: `host-panel-${hostName}-${props.rowIndex}`, + params: { + hostName, + }, + } as HostRightPanelProps, + }); + }, [openFlyout, hostName, props.rowIndex]); + + const panels: ExpandableFlyoutProps['registeredPanels'] = useMemo(() => { + return [ + { + key: `host-panel-${hostName}-${props.rowIndex}`, + component: (panelProps) => { + return ; + }, + }, + ]; + }, [hostName, props.rowIndex]); + + return ( + <> + + {hostName} + + ); +}); + +export const HostCellWithFlyoutRenderer = withExpandableFlyoutProvider( + HostCellWithFlyoutRendererComp +); diff --git a/x-pack/packages/security-solution/common/src/cells/renderers/index.ts b/x-pack/packages/security-solution/common/src/cells/renderers/index.ts new file mode 100644 index 0000000000000..e42333a710c04 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/cells/renderers/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 * from './get'; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.stories.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.stories.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.stories.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.stories.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.test.tsx similarity index 97% rename from x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.test.tsx index 483ee3d378bbd..cc282eb1156b5 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.test.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.test.tsx @@ -13,12 +13,12 @@ import { EXPANDABLE_PANEL_CONTENT_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from './test_ids'; -import { ThemeProvider } from 'styled-components'; -import { getMockTheme } from '../../../common/lib/kibana/kibana_react.mock'; +} from '../test_ids'; +import { ThemeProvider } from '@emotion/react'; import { ExpandablePanel } from './expandable_panel'; -const mockTheme = getMockTheme({ eui: { euiColorMediumShade: '#ece' } }); +const mockTheme = { eui: { euiColorMediumShade: '#ece' } }; + const TEST_ID = 'test-id'; const defaultProps = { header: { diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx similarity index 97% rename from x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx index aa97446f701e1..4f1890e58554f 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx @@ -102,7 +102,7 @@ export const ExpandablePanel: FC> = > = diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_body.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_body.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_body.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_body.test.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_body.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_body.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_body.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_body.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.stories.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.stories.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.stories.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.stories.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.test.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.test.tsx index e58d586a063b5..f0565fe1df43f 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.test.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { render } from '@testing-library/react'; import { FlyoutError } from './flyout_error'; -import { FLYOUT_ERROR_TEST_ID } from './test_ids'; +import { FLYOUT_ERROR_TEST_ID } from '../test_ids'; describe('', () => { it('should render error title and body', () => { diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.tsx similarity index 84% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.tsx index 9ebef345540fe..f319d80dafe12 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_error.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiEmptyPrompt, EuiFlexItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { FLYOUT_ERROR_TEST_ID } from './test_ids'; +import { FLYOUT_ERROR_TEST_ID } from '../test_ids'; /** * Use this when you need to show an error state in the flyout @@ -21,7 +21,7 @@ export const FlyoutError: React.VFC = () => ( title={

@@ -30,7 +30,7 @@ export const FlyoutError: React.VFC = () => ( body={

diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_footer.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_footer.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_footer.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_footer.test.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_footer.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_footer.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_footer.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_footer.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header.test.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header_tabs.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header_tabs.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header_tabs.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header_tabs.test.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header_tabs.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header_tabs.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header_tabs.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header_tabs.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.stories.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.stories.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.stories.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.stories.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.test.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.test.tsx index a164db8a6ce01..d55e85b3e978b 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.test.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { FLYOUT_LOADING_TEST_ID } from './test_ids'; +import { FLYOUT_LOADING_TEST_ID } from '../test_ids'; import { FlyoutLoading } from './flyout_loading'; describe('', () => { diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.tsx index 0c98957dd929b..cffe17c8ccbf1 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_loading.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; import { css } from '@emotion/react'; -import { FLYOUT_LOADING_TEST_ID } from './test_ids'; +import { FLYOUT_LOADING_TEST_ID } from '../test_ids'; export interface FlyoutLoadingProps { /** diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.stories.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.stories.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.stories.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.stories.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.test.tsx similarity index 78% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.test.tsx index 321245ccde86e..d010796008880 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.test.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.test.tsx @@ -8,39 +8,61 @@ import type { FC, PropsWithChildren } from 'react'; import React from 'react'; import { act, render } from '@testing-library/react'; -import { TestProviders } from '../../../common/mock'; import { FlyoutNavigation } from './flyout_navigation'; import { COLLAPSE_DETAILS_BUTTON_TEST_ID, EXPAND_DETAILS_BUTTON_TEST_ID, HEADER_ACTIONS_TEST_ID, -} from './test_ids'; -import type { ExpandableFlyoutState } from '@kbn/expandable-flyout'; +} from '../test_ids'; import { + ExpandableFlyoutApi, + ExpandableFlyoutProvider, + ExpandableFlyoutState, useExpandableFlyoutApi, - type ExpandableFlyoutApi, useExpandableFlyoutState, } from '@kbn/expandable-flyout'; +import { I18nProvider } from '@kbn/i18n-react'; const expandDetails = jest.fn(); - -const ExpandableFlyoutTestProviders: FC> = ({ children }) => { - return {children}; -}; +const mockFlyoutCloseLeftPanel = jest.fn(); jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), + useExpandableFlyoutApi: jest.fn(() => { + return { + closeFlyout: jest.fn(), + closeLeftPanel: jest.fn(), + closePreviewPanel: jest.fn(), + closeRightPanel: jest.fn(), + previousPreviewPanel: jest.fn(), + openFlyout: jest.fn(), + openLeftPanel: jest.fn(), + openPreviewPanel: jest.fn(), + openRightPanel: jest.fn(), + }; + }), useExpandableFlyoutState: jest.fn(), ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, + withExpandableFlyoutProvider: (Component: React.ComponentType) => { + return (props: T) => { + return ; + }; + }, + ExpandableFlyout: jest.fn(), })); -const flyoutContextValue = { - closeLeftPanel: jest.fn(), -} as unknown as ExpandableFlyoutApi; +const ExpandableFlyoutTestProviders: FC> = ({ children }) => { + return ( + + {children} + + ); +}; describe('', () => { beforeEach(() => { - jest.mocked(useExpandableFlyoutApi).mockReturnValue(flyoutContextValue); + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + closeLeftPanel: mockFlyoutCloseLeftPanel, + } as unknown as ExpandableFlyoutApi); jest.mocked(useExpandableFlyoutState).mockReturnValue({} as unknown as ExpandableFlyoutState); }); @@ -75,7 +97,7 @@ describe('', () => { expect(queryByTestId(EXPAND_DETAILS_BUTTON_TEST_ID)).not.toBeInTheDocument(); getByTestId(COLLAPSE_DETAILS_BUTTON_TEST_ID).click(); - expect(flyoutContextValue.closeLeftPanel).toHaveBeenCalled(); + expect(mockFlyoutCloseLeftPanel).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.tsx similarity index 91% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.tsx index 35e684e35613a..c67f20119031e 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.tsx @@ -23,7 +23,7 @@ import { COLLAPSE_DETAILS_BUTTON_TEST_ID, EXPAND_DETAILS_BUTTON_TEST_ID, HEADER_NAVIGATION_BUTTON_TEST_ID, -} from './test_ids'; +} from '../test_ids'; export interface FlyoutNavigationProps { /** @@ -62,14 +62,14 @@ export const FlyoutNavigation: FC = memo( size="s" data-test-subj={COLLAPSE_DETAILS_BUTTON_TEST_ID} aria-label={i18n.translate( - 'xpack.securitySolution.flyout.right.header.collapseDetailButtonAriaLabel', + 'securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel', { defaultMessage: 'Collapse details', } )} > @@ -86,14 +86,14 @@ export const FlyoutNavigation: FC = memo( size="s" data-test-subj={EXPAND_DETAILS_BUTTON_TEST_ID} aria-label={i18n.translate( - 'xpack.securitySolution.flyout.right.header.expandDetailButtonAriaLabel', + 'securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel', { defaultMessage: 'Expand details', } )} > diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.stories.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.stories.tsx index 063e9fe9ef38f..867430167a349 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.stories.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { EuiLink } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { FlyoutTitle } from './flyout_title'; const FixWidthWrapper = styled.div` diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.test.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.test.tsx index 1f2d0c128f411..3fde2b034219b 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.tsx +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.test.tsx @@ -12,7 +12,7 @@ import { TITLE_HEADER_ICON_TEST_ID, TITLE_HEADER_TEXT_TEST_ID, TITLE_LINK_ICON_TEST_ID, -} from './test_ids'; +} from '../test_ids'; const title = 'test title'; const TEST_ID = 'test'; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx b/x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx rename to x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.tsx diff --git a/x-pack/packages/security-solution/common/src/flyout/common/components/index.ts b/x-pack/packages/security-solution/common/src/flyout/common/components/index.ts new file mode 100644 index 0000000000000..4624ae2f70c55 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/flyout/common/components/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { FlyoutFooter } from './flyout_footer'; +export { FlyoutError } from './flyout_error'; +export { FlyoutLoading } from './flyout_loading'; +export { FlyoutNavigation } from './flyout_navigation'; +export { FlyoutTitle } from './flyout_title'; +export { FlyoutBody } from './flyout_body'; +export { FlyoutHeader } from './flyout_header'; +export { FlyoutHeaderTabs } from './flyout_header_tabs'; +export { ExpandablePanel } from './expandable_panel'; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts b/x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts similarity index 97% rename from x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts rename to x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts index 9df26dbfb694d..60ccb0a234fde 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts +++ b/x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PREFIX } from '../test_ids'; +export const PREFIX = 'securitySolutionFlyout' as const; export const FLYOUT_ERROR_TEST_ID = `${PREFIX}Error` as const; export const FLYOUT_LOADING_TEST_ID = `${PREFIX}Loading` as const; diff --git a/x-pack/packages/security-solution/common/src/flyout/index.tsx b/x-pack/packages/security-solution/common/src/flyout/index.tsx new file mode 100644 index 0000000000000..e919538d497c6 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/flyout/index.tsx @@ -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 './common/components'; +export * from './common/test_ids'; +export { HostRightPanel } from './panels'; diff --git a/x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx b/x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx new file mode 100644 index 0000000000000..d877695f5b170 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx @@ -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 { FlyoutPanelProps } from '@kbn/expandable-flyout'; +import React from 'react'; +import { + FlyoutBody, + FlyoutFooter, + FlyoutHeader, + FlyoutNavigation, +} from '../../../common/components'; +// import { getEntityTableColumns } from './columns'; +// import type { BasicEntityData, EntityTableRows } from './types'; + +export interface HostRightPanelParamProps extends Record { + hostName: string; +} + +export interface HostRightPanelProps extends FlyoutPanelProps { + key: 'host'; + params: HostRightPanelParamProps; +} + +export const HostRightPanel = (props: HostRightPanelParamProps) => { + return ( + <> + + {`Host Flyout Header - ${props.hostName}`} + {'Host Flyout'} + {'Host Flyout Footer'} + + ); +}; diff --git a/x-pack/packages/security-solution/common/src/flyout/panels/index.ts b/x-pack/packages/security-solution/common/src/flyout/panels/index.ts new file mode 100644 index 0000000000000..3134078ebdf7f --- /dev/null +++ b/x-pack/packages/security-solution/common/src/flyout/panels/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 './host/right'; +export * from './keys'; diff --git a/x-pack/packages/security-solution/common/src/flyout/panels/keys.ts b/x-pack/packages/security-solution/common/src/flyout/panels/keys.ts new file mode 100644 index 0000000000000..fe06cf652d016 --- /dev/null +++ b/x-pack/packages/security-solution/common/src/flyout/panels/keys.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 const HOST_PANEL = 'host-panel'; diff --git a/x-pack/packages/security-solution/common/tsconfig.json b/x-pack/packages/security-solution/common/tsconfig.json new file mode 100644 index 0000000000000..fb0d3709961d8 --- /dev/null +++ b/x-pack/packages/security-solution/common/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + "@testing-library/jest-dom", + "@testing-library/react", + "@emotion/react/types/css-prop" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "kbn_references": [ + "@kbn/unified-data-table", + "@kbn/discover-utils", + "@kbn/expandable-flyout", + "@kbn/i18n", + "@kbn/i18n-react" + ], + "exclude": [ + "target/**/*" + ] +} diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx index 8f647d02a626f..344370c0f165f 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx @@ -11,10 +11,9 @@ import React from 'react'; import { TestProviders } from '../../../common/mock'; import { getFieldMarkdownRenderer } from '.'; +import { createExpandableFlyoutApiMock } from '../../../common/mock/expandable_flyout'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), -})); +jest.mock('@kbn/expandable-flyout'); describe('getFieldMarkdownRenderer', () => { const mockOpenRightPanel = jest.fn(); @@ -26,14 +25,7 @@ describe('getFieldMarkdownRenderer', () => { jest.clearAllMocks(); mockUseExpandableFlyoutApi.mockReturnValue({ - closeFlyout: jest.fn(), - closeLeftPanel: jest.fn(), - closePreviewPanel: jest.fn(), - closeRightPanel: jest.fn(), - previousPreviewPanel: jest.fn(), - openFlyout: jest.fn(), - openLeftPanel: jest.fn(), - openPreviewPanel: jest.fn(), + ...createExpandableFlyoutApiMock(), openRightPanel: mockOpenRightPanel, }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx index a680590d3752a..17039cd443888 100644 --- a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.test.tsx @@ -16,6 +16,9 @@ import type { RouteSpyState } from '../../../utils/route/types'; import { SecurityPageName } from '@kbn/deeplinks-security'; import { createTelemetryServiceMock } from '../../../lib/telemetry/telemetry_service.mock'; import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/shared/constants/panel_keys'; +import type { ExpandableFlyoutState } from '@kbn/expandable-flyout'; +import { useExpandableFlyoutApi, useExpandableFlyoutState } from '@kbn/expandable-flyout'; +import { createExpandableFlyoutApiMock } from '../../../mock/expandable_flyout'; const mockDispatch = jest.fn(); jest.mock('react-redux', () => { @@ -26,16 +29,11 @@ jest.mock('react-redux', () => { useDispatch: () => mockDispatch, }; }); -const mockOpenFlyout = jest.fn(); jest.mock('../../../utils/route/use_route_spy'); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ openFlyout: mockOpenFlyout }), - useExpandableFlyoutState: () => ({ left: false }), - }; -}); +const mockOpenFlyout = jest.fn(); +jest.mock('@kbn/expandable-flyout'); const mockedTelemetry = createTelemetryServiceMock(); jest.mock('../../../lib/kibana', () => { @@ -102,6 +100,11 @@ describe('RowAction', () => { }; beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + ...createExpandableFlyoutApiMock(), + openFlyout: mockOpenFlyout, + }); + jest.mocked(useExpandableFlyoutState).mockReturnValue({} as unknown as ExpandableFlyoutState); (useRouteSpy as jest.Mock).mockReturnValue([mockRouteSpy]); jest.clearAllMocks(); }); diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 14800d0a2b78f..27a6d28418e9e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -58,6 +58,7 @@ import { indexPatternFieldEditorPluginMock } from '@kbn/data-view-field-editor-p import { UpsellingService } from '@kbn/security-solution-upselling/service'; import { calculateBounds } from '@kbn/data-plugin/common'; import { alertingPluginMock } from '@kbn/alerting-plugin/public/mocks'; +import { createTelemetryServiceMock } from '../telemetry/telemetry_service.mock'; const mockUiSettings: Record = { [DEFAULT_TIME_RANGE]: { from: 'now-15m', to: 'now', mode: 'quick' }, @@ -214,7 +215,7 @@ export const createStartServicesMock = ( ml: { locator, }, - telemetry: {}, + telemetry: createTelemetryServiceMock(), theme: themeServiceMock.createSetupContract(), timelines: { getLastUpdated: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/mock/expandable_flyout.tsx b/x-pack/plugins/security_solution/public/common/mock/expandable_flyout.tsx new file mode 100644 index 0000000000000..a987e99a67d0e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/mock/expandable_flyout.tsx @@ -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 React from 'react'; + +export const createExpandableFlyoutApiMock = () => ({ + closeFlyout: jest.fn(), + closeLeftPanel: jest.fn(), + closePreviewPanel: jest.fn(), + closeRightPanel: jest.fn(), + previousPreviewPanel: jest.fn(), + openFlyout: jest.fn(), + openLeftPanel: jest.fn(), + openPreviewPanel: jest.fn(), + openRightPanel: jest.fn(), +}); + +export const createExpandableFlyoutMock = () => { + return { + useExpandableFlyoutApi: jest.fn().mockReturnValue(createExpandableFlyoutApiMock()), + useExpandableFlyoutState: jest.fn(), + ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, + withExpandableFlyoutProvider: (Component: React.ComponentType) => { + return (props: T) => { + return ; + }; + }, + ExpandableFlyout: jest.fn(), + }; +}; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx index 7de22b5a529b0..d398d380f8a5d 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx @@ -15,6 +15,7 @@ import { useKibana as mockUseKibana } from '../../../common/lib/kibana/__mocks__ import { createTelemetryServiceMock } from '../../../common/lib/telemetry/telemetry_service.mock'; import { useRiskScore } from '../../api/hooks/use_risk_score'; import { useRiskScoreKpi } from '../../api/hooks/use_risk_score_kpi'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; const mockedTelemetry = createTelemetryServiceMock(); const mockedUseKibana = mockUseKibana(); @@ -70,18 +71,15 @@ jest.mock('../../../common/hooks/use_navigate_to_alerts_page_with_filters', () = }); const mockOpenRightPanel = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ - openRightPanel: mockOpenRightPanel, - }), - }; -}); +jest.mock('@kbn/expandable-flyout'); describe.each([RiskScoreEntity.host, RiskScoreEntity.user])( 'EntityAnalyticsRiskScores entityType: %s', (riskEntity) => { beforeEach(() => { + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ + openRightPanel: mockOpenRightPanel, + }); jest.clearAllMocks(); mockUseRiskScoreKpi.mockReturnValue({ severityCount: mockSeverityCount, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx index d9c7f61201789..21ea627d3f65d 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx @@ -22,6 +22,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { euiThemeVars } from '@kbn/ui-theme'; import dateMath from '@kbn/datemath'; import { i18n } from '@kbn/i18n'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { ENABLE_ASSET_CRITICALITY_SETTING } from '../../../../common/constants'; import { useKibana, useUiSetting$ } from '../../../common/lib/kibana/kibana_react'; @@ -32,7 +33,6 @@ import { ONE_WEEK_IN_HOURS } from '../../../flyout/entity_details/shared/constan import { FormattedRelativePreferenceDate } from '../../../common/components/formatted_date'; import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine'; import { VisualizationEmbeddable } from '../../../common/components/visualization_actions/visualization_embeddable'; -import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel'; import type { RiskScoreState } from '../../api/hooks/use_risk_score'; import { getRiskScoreSummaryAttributes } from '../../lens_attributes/risk_score_summary'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/alert_reason.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/alert_reason.tsx index 62e6e9f492b2f..03b84bc625552 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/alert_reason.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/alert_reason.tsx @@ -10,11 +10,11 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import styled from '@emotion/styled'; import { euiThemeVars } from '@kbn/ui-theme'; import { FormattedMessage } from '@kbn/i18n-react'; +import { FlyoutError } from '@kbn/security-solution-common'; import { ALERT_REASON_BODY_TEST_ID } from './test_ids'; import { useAlertReasonPanelContext } from './context'; import { getRowRenderer } from '../../../timelines/components/timeline/body/renderers/get_row_renderer'; import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers'; -import { FlyoutError } from '../../shared/components/flyout_error'; const ReasonContainerWrapper = styled.div` overflow-x: auto; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/context.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/context.tsx index b67c9af508d96..ec8096d60e72c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/context.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/alert_reason/context.tsx @@ -7,9 +7,8 @@ import React, { createContext, memo, useContext, useMemo } from 'react'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; +import { FlyoutError, FlyoutLoading } from '@kbn/security-solution-common'; import { useEventDetails } from '../shared/hooks/use_event_details'; -import { FlyoutError } from '../../shared/components/flyout_error'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; import type { AlertReasonPanelProps } from '.'; export interface AlertReasonPanelContext { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx index 0c9f05391d82a..6ae172ca62556 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx @@ -8,6 +8,7 @@ import type { FC } from 'react'; import React, { useCallback } from 'react'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { DocumentDetailsRightPanelKey } from '../shared/constants/panel_keys'; import { useBasicDataFromDetailsData } from '../shared/hooks/use_basic_data_from_details_data'; import { @@ -16,7 +17,6 @@ import { } from '../../../common/components/endpoint/host_isolation'; import { useHostIsolation } from '../shared/hooks/use_host_isolation'; import { useIsolateHostPanelContext } from './context'; -import { FlyoutBody } from '../../shared/components/flyout_body'; /** * Document details expandable flyout section content for the isolate host component, displaying the form or the success banner diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/context.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/context.tsx index 53393e2f8a79b..6abfe1c4e8650 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/context.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/context.tsx @@ -8,9 +8,8 @@ import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import React, { createContext, memo, useContext, useMemo } from 'react'; +import { FlyoutError, FlyoutLoading } from '@kbn/security-solution-common'; import { useEventDetails } from '../shared/hooks/use_event_details'; -import { FlyoutError } from '../../shared/components/flyout_error'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; import type { IsolateHostPanelProps } from '.'; export interface IsolateHostPanelContext { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx index aa4c04623dfba..80f75f9808620 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx @@ -8,12 +8,12 @@ import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; import type { FC } from 'react'; import React, { useMemo } from 'react'; +import { FlyoutHeader } from '@kbn/security-solution-common'; import { AgentTypeIntegration } from '../../../common/components/endpoint/agents/agent_type_integration'; import { useAlertResponseActionsSupport } from '../../../common/hooks/endpoint/use_alert_response_actions_support'; import { TECHNICAL_PREVIEW, TECHNICAL_PREVIEW_TOOLTIP } from '../../../common/translations'; import { useIsolateHostPanelContext } from './context'; import { FLYOUT_HEADER_TITLE_TEST_ID } from './test_ids'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; import { ISOLATE_HOST, UNISOLATE_HOST } from '../../../common/components/endpoint'; /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx index b3b129a75c13d..859da37c4082d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx @@ -28,7 +28,7 @@ import { useFetchRelatedAlertsBySameSourceEvent } from '../../shared/hooks/use_f import { useFetchRelatedCases } from '../../shared/hooks/use_fetch_related_cases'; import { mockContextValue } from '../../shared/mocks/mock_context'; import { useTimelineDataFilters } from '../../../../timelines/containers/use_timeline_data_filters'; -import { EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID } from '../../../shared/components/test_ids'; +import { EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID } from '@kbn/security-solution-common'; jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.test.tsx index f9391fe8fec06..ddf05af5d3908 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.test.tsx @@ -22,10 +22,7 @@ jest.mock('../hooks/use_paginated_alerts'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const TEST_ID = 'TEST'; const alertIds = ['id1', 'id2', 'id3']; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx index 178adabb80700..70b238825d66a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx @@ -14,12 +14,12 @@ import { isRight } from 'fp-ts/lib/Either'; import { ALERT_REASON, ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { CellTooltipWrapper } from '../../shared/components/cell_tooltip_wrapper'; import type { DataProvider } from '../../../../../common/types'; import { SeverityBadge } from '../../../../common/components/severity_badge'; import { usePaginatedAlerts } from '../hooks/use_paginated_alerts'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import { InvestigateInTimelineButton } from '../../../../common/components/event_details/table/investigate_in_timeline_button'; import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../../detections/components/alerts_table/translations'; import { getDataProvider } from '../../../../common/components/event_details/table/use_action_cell_data_provider'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx index d9d468649a221..b6c5dc0078b02 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx @@ -13,7 +13,7 @@ import { TestProviders } from '../../../../common/mock'; import { EntitiesDetails } from './entities_details'; import { ENTITIES_DETAILS_TEST_ID, HOST_DETAILS_TEST_ID, USER_DETAILS_TEST_ID } from './test_ids'; import { mockContextValue } from '../../shared/mocks/mock_context'; -import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../../shared/components/test_ids'; +import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '@kbn/security-solution-common'; import type { Anomalies } from '../../../../common/components/ml/types'; import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; import { mockAnomalies } from '../../../../common/components/ml/mock'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx index 213bfbbecaa25..7ba3d7823f24d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx @@ -24,7 +24,7 @@ import { HOST_DETAILS_LINK_TEST_ID, HOST_DETAILS_RELATED_USERS_LINK_TEST_ID, } from './test_ids'; -import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../../shared/components/test_ids'; +import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '@kbn/security-solution-common'; import { useRiskScore } from '../../../../entity_analytics/api/hooks/use_risk_score'; import { mockContextValue } from '../../shared/mocks/mock_context'; import { mockFlyoutApi } from '../../shared/mocks/mock_flyout_context'; @@ -34,10 +34,7 @@ import { HOST_PREVIEW_BANNER } from '../../right/components/host_entity_overview import { UserPreviewPanelKey } from '../../../entity_details/user_right'; import { USER_PREVIEW_BANNER } from '../../right/components/user_entity_overview'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx index 594409c82f880..49813f43d3de1 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx @@ -24,8 +24,8 @@ import type { EuiBasicTableColumn } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import type { RelatedUser } from '../../../../../common/search_strategy/security_solution/related_entities/related_users'; import type { RiskSeverity } from '../../../../../common/search_strategy'; import { HostOverview } from '../../../../overview/components/host_overview'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/investigation_guide.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/investigation_guide.tsx index ee1bebdb336ce..f39057a16bfdb 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/investigation_guide.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/investigation_guide.tsx @@ -7,11 +7,11 @@ import React from 'react'; import { EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { FlyoutLoading } from '@kbn/security-solution-common'; import { useInvestigationGuide } from '../../shared/hooks/use_investigation_guide'; import { useDocumentDetailsContext } from '../../shared/context'; import { INVESTIGATION_GUIDE_TEST_ID, INVESTIGATION_GUIDE_LOADING_TEST_ID } from './test_ids'; import { InvestigationGuideView } from './investigation_guide_view'; -import { FlyoutLoading } from '../../../shared/components/flyout_loading'; /** * Investigation guide displayed in the left panel. diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx index 5b7da67186e34..f1abc48f0e87a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.test.tsx @@ -33,10 +33,7 @@ import { HOST_PREVIEW_BANNER } from '../../right/components/host_entity_overview import { UserPreviewPanelKey } from '../../../entity_details/user_right'; import { USER_PREVIEW_BANNER } from '../../right/components/user_entity_overview'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx index 52468f0aedbb9..62012b72052bc 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx @@ -20,7 +20,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { usePaginatedAlerts } from '../hooks/use_paginated_alerts'; jest.mock('../../shared/hooks/use_fetch_related_alerts_by_ancestry'); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_same_source_event.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_same_source_event.test.tsx index 3cf2d93896bc3..f4244fcc59a04 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_same_source_event.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_same_source_event.test.tsx @@ -20,7 +20,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { usePaginatedAlerts } from '../hooks/use_paginated_alerts'; jest.mock('../../shared/hooks/use_fetch_related_alerts_by_same_source_event'); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_session.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_session.test.tsx index 0120f462b9ac5..54df7e8924f68 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_session.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_session.test.tsx @@ -21,7 +21,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; jest.mock('../../shared/hooks/use_fetch_related_alerts_by_session'); jest.mock('../hooks/use_paginated_alerts'); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.test.tsx index db9eb7bdfb3ae..4d90cc7f56133 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.test.tsx @@ -18,7 +18,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; jest.mock('../../shared/hooks/use_fetch_related_cases'); jest.mock('../../../../common/components/links', () => ({ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.tsx index 13df33a2deb1b..8e00e0e65478b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_cases.tsx @@ -10,6 +10,7 @@ import type { EuiBasicTableColumn } from '@elastic/eui'; import { EuiInMemoryTable } from '@elastic/eui'; import type { RelatedCase } from '@kbn/cases-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { CellTooltipWrapper } from '../../shared/components/cell_tooltip_wrapper'; import { CaseDetailsLink } from '../../../../common/components/links'; import { @@ -17,7 +18,6 @@ import { CORRELATIONS_DETAILS_CASES_SECTION_TEST_ID, } from './test_ids'; import { useFetchRelatedCases } from '../../shared/hooks/use_fetch_related_cases'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; const ICON = 'warning'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.test.tsx index 3b73199494187..a97a601f082dd 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.test.tsx @@ -17,7 +17,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { DocumentDetailsContext } from '../../shared/context'; import { mockContextValue } from '../../shared/mocks/mock_context'; import { isSuppressionRuleInGA } from '../../../../../common/detection_engine/utils'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx index 02f00264470e0..efd1628f9d70a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx @@ -11,7 +11,7 @@ import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { EuiBetaBadge, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { CORRELATIONS_DETAILS_SUPPRESSED_ALERTS_SECTION_TEST_ID, SUPPRESSED_ALERTS_SECTION_TECHNICAL_PREVIEW_TEST_ID, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/threat_intelligence_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/threat_intelligence_details.tsx index f473ae2c3262b..6ac43fbe5cd31 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/threat_intelligence_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/threat_intelligence_details.tsx @@ -9,6 +9,7 @@ import React, { memo } from 'react'; import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import isEmpty from 'lodash/isEmpty'; import { groupBy } from 'lodash'; +import { FlyoutLoading } from '@kbn/security-solution-common'; import { EnrichmentSection } from './threat_details_view_enrichment_section'; import { ENRICHMENT_TYPES } from '../../../../../common/cti/constants'; import { EnrichmentRangePicker } from './threat_intelligence_view_enrichment_range_picker'; @@ -19,7 +20,6 @@ import { THREAT_INTELLIGENCE_ENRICHMENTS_TEST_ID, THREAT_INTELLIGENCE_MATCHES_TEST_ID, } from './test_ids'; -import { FlyoutLoading } from '../../../shared/components/flyout_loading'; export const THREAT_INTELLIGENCE_TAB_ID = 'threatIntelligence'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/tour.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/tour.tsx index c1bafab10d9a7..196d9113457a3 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/tour.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/tour.tsx @@ -10,9 +10,9 @@ import { useWhichFlyout } from '../../shared/hooks/use_which_flyout'; import { getField } from '../../shared/utils'; import { EventKind } from '../../shared/constants/event_kinds'; import { useDocumentDetailsContext } from '../../shared/context'; -import { FlyoutTour } from '../../shared/components/flyout_tour'; import { getLeftSectionTourSteps } from '../../shared/utils/tour_step_config'; import { Flyouts } from '../../shared/constants/flyouts'; +import { FlyoutTour } from '../../shared/components/flyout_tour'; /** * Guided tour for the left panel in details flyout diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx index 02764d25b975e..ddf0b51f929b8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx @@ -24,7 +24,7 @@ import { USER_DETAILS_RELATED_HOSTS_TABLE_TEST_ID, USER_DETAILS_RELATED_HOSTS_LINK_TEST_ID, } from './test_ids'; -import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../../shared/components/test_ids'; +import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '@kbn/security-solution-common'; import { useRiskScore } from '../../../../entity_analytics/api/hooks/use_risk_score'; import { mockContextValue } from '../../shared/mocks/mock_context'; import { mockFlyoutApi } from '../../shared/mocks/mock_flyout_context'; @@ -34,10 +34,7 @@ import { HOST_PREVIEW_BANNER } from '../../right/components/host_entity_overview import { UserPreviewPanelKey } from '../../../entity_details/user_right'; import { USER_PREVIEW_BANNER } from '../../right/components/user_entity_overview'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx index a3d335b913148..1a93eab1c46e4 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx @@ -24,8 +24,8 @@ import type { EuiBasicTableColumn } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import type { RelatedHost } from '../../../../../common/search_strategy/security_solution/related_entities/related_hosts'; import type { RiskSeverity } from '../../../../../common/search_strategy'; import { UserOverview } from '../../../../overview/components/user_overview'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/content.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/content.tsx index 53d2efe883397..226765e6c4e37 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/content.tsx @@ -9,9 +9,9 @@ import { useEuiBackgroundColor } from '@elastic/eui'; import type { FC } from 'react'; import React, { useMemo } from 'react'; import { css } from '@emotion/react'; +import { FlyoutBody } from '@kbn/security-solution-common'; import type { LeftPanelPaths } from '.'; import type { LeftPanelTabType } from './tabs'; -import { FlyoutBody } from '../../shared/components/flyout_body'; export interface PanelContentProps { /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/header.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/header.tsx index 2b61a97577e06..f276ccca842be 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/header.tsx @@ -9,8 +9,8 @@ import { EuiTab, EuiTabs, useEuiBackgroundColor } from '@elastic/eui'; import type { FC } from 'react'; import React, { memo } from 'react'; import { css } from '@emotion/react'; +import { FlyoutHeader } from '@kbn/security-solution-common'; import type { LeftPanelPaths } from '.'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; import type { LeftPanelTabType } from './tabs'; import { getField } from '../shared/utils'; import { EventKind } from '../shared/constants/event_kinds'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts index 9f5eeb035786c..4e2c1be90b01c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PREFIX } from '../../shared/test_ids'; +import { PREFIX } from '@kbn/security-solution-common'; export const VISUALIZE_TAB_TEST_ID = `${PREFIX}VisualizeTab` as const; export const INSIGHTS_TAB_TEST_ID = `${PREFIX}InsightsTab` as const; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.test.tsx index d0b46038f44e0..2bf185a44942d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.test.tsx @@ -15,10 +15,7 @@ import { DocumentDetailsContext } from '../shared/context'; import { PreviewPanelFooter } from './footer'; import { PREVIEW_FOOTER_TEST_ID, PREVIEW_FOOTER_LINK_TEST_ID } from './test_ids'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); describe('', () => { beforeAll(() => { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.tsx index 0ab0c9f44eb15..404a3debefc2e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/preview/footer.tsx @@ -9,7 +9,7 @@ import { EuiLink, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; -import { FlyoutFooter } from '../../shared/components/flyout_footer'; +import { FlyoutFooter } from '@kbn/security-solution-common'; import { DocumentDetailsRightPanelKey } from '../shared/constants/panel_keys'; import { useDocumentDetailsContext } from '../shared/context'; import { PREVIEW_FOOTER_TEST_ID, PREVIEW_FOOTER_LINK_TEST_ID } from './test_ids'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_description.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_description.test.tsx index c8a00cf0837fa..4949b97e87917 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_description.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_description.test.tsx @@ -34,7 +34,7 @@ jest.mock('../../../../common/lib/kibana', () => { }; }); -jest.mock('@kbn/expandable-flyout', () => ({ useExpandableFlyoutApi: jest.fn() })); +jest.mock('@kbn/expandable-flyout'); const ruleUuid = { category: 'kibana', diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_header_title.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_header_title.tsx index 8d3b0577230a8..a54a3a027fad1 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_header_title.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/alert_header_title.tsx @@ -10,6 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel, useEuiTheme, EuiLink } import { css } from '@emotion/css'; import { ALERT_WORKFLOW_ASSIGNEE_IDS } from '@kbn/rule-data-utils'; import { i18n } from '@kbn/i18n'; +import { FlyoutTitle } from '@kbn/security-solution-common'; import { useRuleDetailsLink } from '../../shared/hooks/use_rule_details_link'; import { DocumentStatus } from './status'; import { DocumentSeverity } from './severity'; @@ -20,7 +21,6 @@ import { useDocumentDetailsContext } from '../../shared/context'; import { PreferenceFormattedDate } from '../../../../common/components/formatted_date'; import { FLYOUT_ALERT_HEADER_TITLE_TEST_ID, ALERT_SUMMARY_PANEL_TEST_ID } from './test_ids'; import { Assignees } from './assignees'; -import { FlyoutTitle } from '../../../shared/components/flyout_title'; /** * Alert details flyout right section header diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.test.tsx index 7dae9400358c5..550bda40e5e68 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.test.tsx @@ -21,7 +21,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { mockDataFormattedForFieldBrowser } from '../../shared/mocks/mock_data_formatted_for_field_browser'; import { useInvestigateInTimeline } from '../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.tsx index ad85e8e8701e1..f3d99d9144ad2 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview_container.tsx @@ -10,6 +10,7 @@ import { useDispatch } from 'react-redux'; import { TimelineTabs } from '@kbn/securitysolution-data-table'; import { EuiLink, EuiMark } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { useInvestigateInTimeline } from '../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline'; import { ALERTS_ACTIONS } from '../../../../common/lib/apm/user_actions'; @@ -19,7 +20,6 @@ import { useDocumentDetailsContext } from '../../shared/context'; import { useIsInvestigateInResolverActionEnabled } from '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'; import { AnalyzerPreview } from './analyzer_preview'; import { ANALYZER_PREVIEW_TEST_ID } from './test_ids'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; const timelineId = 'timeline-1'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.test.tsx index fb6b2f4edcfb2..f4a97b7deed11 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.test.tsx @@ -39,7 +39,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { useTourContext } from '../../../../common/components/guided_onboarding_tour'; import { AlertsCasesTourSteps } from '../../../../common/components/guided_onboarding_tour/tour_config'; @@ -92,10 +92,7 @@ const flyoutContextValue = { openLeftPanel: jest.fn(), } as unknown as ExpandableFlyoutApi; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../timelines/containers/use_timeline_data_filters', () => ({ useTimelineDataFilters: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx index d4e9a6fe58113..058db7c8dc79e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx @@ -12,7 +12,7 @@ import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { FormattedMessage } from '@kbn/i18n-react'; import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useShowRelatedAlertsBySession } from '../../shared/hooks/use_show_related_alerts_by_session'; import { RelatedAlertsBySession } from './related_alerts_by_session'; import { useShowRelatedAlertsBySameSourceEvent } from '../../shared/hooks/use_show_related_alerts_by_same_source_event'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx index 92248c6de2828..e4975d3136424 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx @@ -24,7 +24,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { useRiskScore } from '../../../../entity_analytics/api/hooks/use_risk_score'; const from = '2022-04-05T12:00:00.000Z'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.tsx index 16fe6cbe1c1e0..60657a1346101 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.tsx @@ -9,8 +9,8 @@ import React, { useCallback, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { FormattedMessage } from '@kbn/i18n-react'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { INSIGHTS_ENTITIES_TEST_ID } from './test_ids'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import { useDocumentDetailsContext } from '../../shared/context'; import { getField } from '../../shared/utils'; import { HostEntityOverview } from './host_entity_overview'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_header_title.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_header_title.tsx index 953a2371ffa88..f93b8451c744a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_header_title.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_header_title.tsx @@ -9,7 +9,7 @@ import React, { memo, useMemo } from 'react'; import { startCase } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FlyoutTitle } from '../../../shared/components/flyout_title'; +import { FlyoutTitle } from '@kbn/security-solution-common'; import { DocumentSeverity } from './severity'; import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data'; import { useDocumentDetailsContext } from '../../shared/context'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.test.tsx index 3ebb00c3b7c75..0426d9861b93c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.test.tsx @@ -30,10 +30,7 @@ import { USER_PREVIEW_BANNER } from './user_entity_overview'; jest.mock('../../../../management/hooks'); jest.mock('../../../../management/hooks/agents/use_get_agent_status'); -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const useGetAgentStatusMock = useGetAgentStatus as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.test.tsx index f554f578c86cd..dcaf51761239d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.test.tsx @@ -44,10 +44,7 @@ const panelContextValue = { dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, }; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/investigation_guide.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/investigation_guide.test.tsx index 74f532fc6809b..f70039230cc45 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/investigation_guide.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/investigation_guide.test.tsx @@ -23,7 +23,7 @@ import { DocumentDetailsLeftPanelKey } from '../../shared/constants/panel_keys'; import { LeftPanelInvestigationTab } from '../../left'; jest.mock('../../shared/hooks/use_investigation_guide'); -jest.mock('@kbn/expandable-flyout', () => ({ useExpandableFlyoutApi: jest.fn() })); +jest.mock('@kbn/expandable-flyout'); const mockFlyoutContextValue = { openLeftPanel: jest.fn() }; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.test.tsx index 6b3e287d80915..a47ed04c85b5a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.test.tsx @@ -20,7 +20,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_LOADING_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { mockContextValue } from '../../shared/mocks/mock_context'; import { type ExpandableFlyoutApi, useExpandableFlyoutApi } from '@kbn/expandable-flyout'; @@ -38,10 +38,7 @@ const flyoutContextValue = { openLeftPanel: jest.fn(), } as unknown as ExpandableFlyoutApi; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const renderPrevalenceOverview = (contextValue: DocumentDetailsContext = mockContextValue) => render( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.tsx index 3776e486b426b..96ee603607742 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/prevalence_overview.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useMemo } from 'react'; import { EuiFlexGroup } from '@elastic/eui'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { PREVALENCE_TEST_ID } from './test_ids'; import { useDocumentDetailsContext } from '../../shared/context'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/reason.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/reason.test.tsx index e69f2d833e949..f4faa9a3d730e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/reason.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/reason.test.tsx @@ -33,10 +33,7 @@ jest.mock('../../../../common/lib/kibana', () => { }; }); -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const panelContextValue = { eventId: 'event id', diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.test.tsx index f6f56f1c9cd2a..26bbdcebe22f1 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.test.tsx @@ -19,7 +19,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID, EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; import { mockGetFieldsData } from '../../shared/mocks/mock_get_fields_data'; jest.mock('../hooks/use_session_preview'); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx index 43a19667d4fb6..aa97b904c1381 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx @@ -11,13 +11,13 @@ import { useDispatch } from 'react-redux'; import { EuiLink, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/css'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useLicense } from '../../../../common/hooks/use_license'; import { SessionPreview } from './session_preview'; import { useSessionPreview } from '../hooks/use_session_preview'; import { useInvestigateInTimeline } from '../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline'; import { useDocumentDetailsContext } from '../../shared/context'; import { ALERTS_ACTIONS } from '../../../../common/lib/apm/user_actions'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import { SESSION_PREVIEW_TEST_ID } from './test_ids'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { setActiveTabTimeline } from '../../../../timelines/store/actions'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.test.tsx index 2e2ffa99efe42..af92283b781b5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.test.tsx @@ -23,7 +23,7 @@ import { EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID, EXPANDABLE_PANEL_LOADING_TEST_ID, EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, -} from '../../../shared/components/test_ids'; +} from '@kbn/security-solution-common'; jest.mock('../hooks/use_fetch_threat_intelligence'); @@ -48,10 +48,7 @@ const panelContextValue = { dataFormattedForFieldBrowser: [], } as unknown as DocumentDetailsContext; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const renderThreatIntelligenceOverview = (contextValue: DocumentDetailsContext) => ( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.tsx index ca47113ad12c3..10b23ecfc2340 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/threat_intelligence_overview.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useMemo } from 'react'; import { EuiFlexGroup } from '@elastic/eui'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { useFetchThreatIntelligence } from '../hooks/use_fetch_threat_intelligence'; import { InsightsSummaryRow } from './insights_summary_row'; import { useDocumentDetailsContext } from '../../shared/context'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/tour.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/tour.tsx index 093a93149285c..839b77766886a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/tour.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/tour.tsx @@ -10,7 +10,6 @@ import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { useWhichFlyout } from '../../shared/hooks/use_which_flyout'; import { Flyouts } from '../../shared/constants/flyouts'; import { useDocumentDetailsContext } from '../../shared/context'; -import { FlyoutTour } from '../../shared/components/flyout_tour'; import { getRightSectionTourSteps, getLeftSectionTourSteps, @@ -24,6 +23,7 @@ import { EventKind } from '../../shared/constants/event_kinds'; import { useTourContext } from '../../../../common/components/guided_onboarding_tour/tour'; import { SecurityStepId } from '../../../../common/components/guided_onboarding_tour/tour_config'; import { useKibana } from '../../../../common/lib/kibana'; +import { FlyoutTour } from '../../shared/components/flyout_tour'; /** * Guided tour for the right panel in details flyout diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.test.tsx index d1d9651b9d5f1..000da8946ff61 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.test.tsx @@ -44,19 +44,11 @@ const panelContextValue = { dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, }; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../common/hooks/use_experimental_features'); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); - const mockUseGlobalTime = jest.fn().mockReturnValue({ from, to }); jest.mock('../../../../common/containers/use_global_time', () => { return { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/content.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/content.tsx index dbc530a4dd3f6..075921de192b8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/content.tsx @@ -7,10 +7,10 @@ import type { FC } from 'react'; import React, { useMemo } from 'react'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { FLYOUT_BODY_TEST_ID } from './test_ids'; import type { RightPanelPaths } from '.'; import type { RightPanelTabType } from './tabs'; -import { FlyoutBody } from '../../shared/components/flyout_body'; export interface PanelContentProps { /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/header.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/header.tsx index 3bf4e1a741251..189fe250fbab2 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/header.tsx @@ -9,10 +9,9 @@ import type { EuiFlyoutHeader } from '@elastic/eui'; import { EuiSpacer, EuiTab } from '@elastic/eui'; import type { FC } from 'react'; import React, { memo, useMemo } from 'react'; +import { FlyoutHeader, FlyoutHeaderTabs } from '@kbn/security-solution-common'; import type { RightPanelPaths } from '.'; import type { RightPanelTabType } from './tabs'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; -import { FlyoutHeaderTabs } from '../../shared/components/flyout_header_tabs'; import { AlertHeaderTitle } from './components/alert_header_title'; import { EventHeaderTitle } from './components/event_header_title'; import { useDocumentDetailsContext } from '../shared/context'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/navigation.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/navigation.tsx index b4f12fbabf94f..79aad96c209db 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/navigation.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/navigation.tsx @@ -8,9 +8,9 @@ import type { FC } from 'react'; import React, { memo, useCallback } from 'react'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { FlyoutNavigation } from '@kbn/security-solution-common'; import { useKibana } from '../../../common/lib/kibana'; import { HeaderActions } from './components/header_actions'; -import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; import { DocumentDetailsLeftPanelKey } from '../shared/constants/panel_keys'; import { useDocumentDetailsContext } from '../shared/context'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/footer.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/footer.tsx index ebc204f8cb921..aca0d23027a61 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/footer.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/footer.tsx @@ -8,8 +8,8 @@ import React, { memo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FlyoutFooter } from '@kbn/security-solution-common'; import { useRuleOverviewPanelContext } from '../context'; -import { FlyoutFooter } from '../../../shared/components/flyout_footer'; import { RULE_OVERVIEW_FOOTER_TEST_ID, RULE_OVERVIEW_NAVIGATE_TO_RULE_TEST_ID } from './test_ids'; import { useRuleDetailsLink } from '../../shared/hooks/use_rule_details_link'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/rule_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/rule_overview.tsx index 73f9cc12dd053..2e61501241899 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/rule_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/components/rule_overview.tsx @@ -8,6 +8,7 @@ import React, { memo, useState, useEffect } from 'react'; import { EuiText, EuiHorizontalRule, EuiSpacer, EuiPanel } from '@elastic/eui'; import { css } from '@emotion/css'; import { FormattedMessage } from '@kbn/i18n-react'; +import { FlyoutLoading, FlyoutError } from '@kbn/security-solution-common'; import { useRuleOverviewPanelContext } from '../context'; import { ExpandableSection } from '../../right/components/expandable_section'; import { useRuleWithFallback } from '../../../../detection_engine/rule_management/logic/use_rule_with_fallback'; @@ -17,8 +18,6 @@ import { RuleAboutSection } from '../../../../detection_engine/rule_management/c import { RuleScheduleSection } from '../../../../detection_engine/rule_management/components/rule_details/rule_schedule_section'; import { RuleDefinitionSection } from '../../../../detection_engine/rule_management/components/rule_details/rule_definition_section'; import { StepRuleActionsReadOnly } from '../../../../detection_engine/rule_creation/components/step_rule_actions'; -import { FlyoutLoading } from '../../../shared/components/flyout_loading'; -import { FlyoutError } from '../../../shared/components/flyout_error'; import { RULE_OVERVIEW_BODY_TEST_ID, RULE_OVERVIEW_ABOUT_TEST_ID, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/context.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/context.tsx index 1b379b3c3ece8..cae182b839e6d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/context.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/context.tsx @@ -6,7 +6,7 @@ */ import React, { createContext, memo, useContext, useMemo } from 'react'; -import { FlyoutError } from '../../shared/components/flyout_error'; +import { FlyoutError } from '@kbn/security-solution-common'; import type { RuleOverviewPanelProps } from '.'; export interface RuleOverviewPanelContext { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/index.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/index.tsx index 504be510a09f7..b978a1697bbd5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/rule_overview/index.tsx @@ -7,7 +7,7 @@ import React, { memo } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; -import { FlyoutBody } from '../../shared/components/flyout_body'; +import { FlyoutBody } from '@kbn/security-solution-common'; import type { DocumentDetailsRuleOverviewPanelKey } from '../shared/constants/panel_keys'; import { RuleOverview } from './components/rule_overview'; import { RuleFooter } from './components/footer'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/context.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/context.tsx index 12e2ad4f2a0b6..f2c5d8bfa530f 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/context.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/context.tsx @@ -9,9 +9,8 @@ import type { BrowserFields, TimelineEventsDetailsItem } from '@kbn/timelines-pl import React, { createContext, memo, useContext, useMemo } from 'react'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { TableId } from '@kbn/securitysolution-data-table'; +import { FlyoutError, FlyoutLoading } from '@kbn/security-solution-common/src/flyout'; import { useEventDetails } from './hooks/use_event_details'; -import { FlyoutError } from '../../shared/components/flyout_error'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; import type { SearchHit } from '../../../../common/search_strategy'; import { useBasicDataFromDetailsData } from './hooks/use_basic_data_from_details_data'; import type { DocumentDetailsProps } from './types'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/tour_step_config.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/tour_step_config.tsx index 7b850cca82450..3f597e47c770c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/tour_step_config.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/tour_step_config.tsx @@ -9,7 +9,7 @@ import { EuiText, EuiCode, type EuiTourStepProps } from '@elastic/eui'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { HEADER_NAVIGATION_BUTTON_TEST_ID } from '../../../shared/components/test_ids'; +import { HEADER_NAVIGATION_BUTTON_TEST_ID } from '@kbn/security-solution-common'; import { OVERVIEW_TAB_LABEL_TEST_ID } from '../../right/test_ids'; import { RULE_SUMMARY_BUTTON_TEST_ID } from '../../right/components/test_ids'; import { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.test.tsx index 8bfc575e5b573..403e9cf1c0ed0 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.test.tsx @@ -12,10 +12,7 @@ import { mockFlyoutApi } from '../../document_details/shared/mocks/mock_flyout_c import type { HostPreviewPanelFooterProps } from './footer'; import { HostPreviewPanelFooter } from './footer'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const mockProps: HostPreviewPanelFooterProps = { hostName: 'test', diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.tsx index e550da28b532a..3ea6d7a5e0438 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_preview/footer.tsx @@ -9,7 +9,7 @@ import { EuiLink, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; -import { FlyoutFooter } from '../../shared/components/flyout_footer'; +import { FlyoutFooter } from '@kbn/security-solution-common'; import { HostPanelKey } from '../host_right'; export interface HostPreviewPanelFooterProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx index af3eae38fc1f8..27e824d39c913 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx @@ -7,11 +7,11 @@ import React from 'react'; import { EuiHorizontalRule } from '@elastic/eui'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { AssetCriticalityAccordion } from '../../../entity_analytics/components/asset_criticality/asset_criticality_selector'; import { FlyoutRiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; import type { RiskScoreEntity, HostItem } from '../../../../common/search_strategy'; -import { FlyoutBody } from '../../shared/components/flyout_body'; import { ObservedEntity } from '../shared/components/observed_entity'; import { HOST_PANEL_OBSERVED_HOST_QUERY_ID, HOST_PANEL_RISK_SCORE_QUERY_ID } from '.'; import type { ObservedEntityData } from '../shared/components/observed_entity/types'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx index b5df2f81d1b0a..706790770eb6c 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx @@ -9,12 +9,11 @@ import { EuiSpacer, EuiBadge, EuiText, EuiFlexItem, EuiFlexGroup } from '@elasti import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo } from 'react'; import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { FlyoutHeader, FlyoutTitle } from '@kbn/security-solution-common'; import type { HostItem } from '../../../../common/search_strategy'; import { getHostDetailsUrl } from '../../../common/components/link_to'; import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; import { PreferenceFormattedDate } from '../../../common/components/formatted_date'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; -import { FlyoutTitle } from '../../shared/components/flyout_title'; import type { ObservedEntityData } from '../shared/components/observed_entity/types'; interface HostPanelHeaderProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx index 798bff18b9c16..4799c396a7be3 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useMemo } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { FlyoutLoading, FlyoutNavigation } from '@kbn/security-solution-common'; import { useRefetchQueryById } from '../../../entity_analytics/api/hooks/use_refetch_query_by_id'; import { RISK_INPUTS_TAB_QUERY_ID } from '../../../entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab'; import type { Refetch } from '../../../common/types'; @@ -21,8 +22,6 @@ import { useGlobalTime } from '../../../common/containers/use_global_time'; import type { HostItem } from '../../../../common/search_strategy'; import { buildHostNamesFilter } from '../../../../common/search_strategy'; import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; -import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; import { HostPanelContent } from './content'; import { HostPanelHeader } from './header'; import { AnomalyTableProvider } from '../../../common/components/ml/anomaly/anomaly_table_provider'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx index 5a66a5b305611..f52480285a567 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx @@ -9,7 +9,7 @@ import { useEuiBackgroundColor } from '@elastic/eui'; import type { VFC } from 'react'; import React, { useMemo } from 'react'; import { css } from '@emotion/react'; -import { FlyoutBody } from '../../../../shared/components/flyout_body'; +import { FlyoutBody } from '@kbn/security-solution-common'; import type { EntityDetailsLeftPanelTab, LeftPanelTabsType } from './left_panel_header'; export interface PanelContentProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx index ea62ce25f3ca4..7a537d64aa755 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx @@ -9,7 +9,7 @@ import { EuiTab, EuiTabs, useEuiBackgroundColor } from '@elastic/eui'; import type { ReactElement, VFC } from 'react'; import React, { memo } from 'react'; import { css } from '@emotion/react'; -import { FlyoutHeader } from '../../../../shared/components/flyout_header'; +import { FlyoutHeader } from '@kbn/security-solution-common'; export type LeftPanelTabsType = Array<{ id: EntityDetailsLeftPanelTab; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx index 2ba1e274e0c5b..a04bd739eb299 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx @@ -8,9 +8,9 @@ import React, { useMemo } from 'react'; import type { FlyoutPanelProps, PanelPath } from '@kbn/expandable-flyout'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { FlyoutLoading } from '@kbn/security-solution-common'; import { useManagedUser } from '../shared/hooks/use_managed_user'; import { useTabs } from './tabs'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; import type { EntityDetailsLeftPanelTab, LeftPanelTabsType, diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs/asset_document.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs/asset_document.tsx index 3aa4a72ffe898..31053cf88d931 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs/asset_document.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs/asset_document.tsx @@ -12,10 +12,10 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { EuiButtonGroupOptionProps } from '@elastic/eui'; import { EuiButtonGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { JsonTab } from '../../../document_details/right/tabs/json_tab'; import { TableTab } from '../../../document_details/right/tabs/table_tab'; import { FLYOUT_BODY_TEST_ID, JSON_TAB_TEST_ID, TABLE_TAB_TEST_ID } from './test_ids'; -import { FlyoutBody } from '../../../shared/components/flyout_body'; export type RightPanelPaths = 'overview' | 'table' | 'json'; export interface AssetDocumentPanelProps extends FlyoutPanelProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.test.tsx index 52fcee31028e1..93d14644476ef 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.test.tsx @@ -12,10 +12,7 @@ import { mockFlyoutApi } from '../../document_details/shared/mocks/mock_flyout_c import type { UserPreviewPanelFooterProps } from './footer'; import { UserPreviewPanelFooter } from './footer'; -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: jest.fn(), - ExpandableFlyoutProvider: ({ children }: React.PropsWithChildren<{}>) => <>{children}, -})); +jest.mock('@kbn/expandable-flyout'); const mockProps: UserPreviewPanelFooterProps = { userName: 'test', diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.tsx index 7f55feb7a347c..6921d1a73d4e2 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_preview/footer.tsx @@ -9,7 +9,7 @@ import { EuiLink, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; -import { FlyoutFooter } from '../../shared/components/flyout_footer'; +import { FlyoutFooter } from '@kbn/security-solution-common'; import { UserPanelKey } from '../user_right'; export interface UserPreviewPanelFooterProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/components/managed_user_accordion.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/components/managed_user_accordion.tsx index 8d9007713549e..84f6c96cb772b 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/components/managed_user_accordion.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/components/managed_user_accordion.tsx @@ -11,13 +11,14 @@ import React from 'react'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import { get } from 'lodash/fp'; +import { ExpandablePanel } from '@kbn/security-solution-common'; import { EntityDetailsLeftPanelTab } from '../../shared/components/left_panel/left_panel_header'; -import { ExpandablePanel } from '../../../shared/components/expandable_panel'; import type { ManagedUserFields } from '../../../../../common/search_strategy/security_solution/users/managed_details'; import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; import { ONE_WEEK_IN_HOURS } from '../../shared/constants'; import { UserAssetTableType } from '../../../../explore/users/store/model'; + interface ManagedUserAccordionProps { children: React.ReactNode; title: string; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx index d06309ea09d02..26945a12f8bd6 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx @@ -8,6 +8,7 @@ import { EuiHorizontalRule } from '@elastic/eui'; import React from 'react'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { AssetCriticalityAccordion } from '../../../entity_analytics/components/asset_criticality/asset_criticality_selector'; @@ -18,7 +19,6 @@ import { ManagedUser } from './components/managed_user'; import type { ManagedUserData } from './types'; import type { RiskScoreEntity, UserItem } from '../../../../common/search_strategy'; import { USER_PANEL_RISK_SCORE_QUERY_ID } from '.'; -import { FlyoutBody } from '../../shared/components/flyout_body'; import { ObservedEntity } from '../shared/components/observed_entity'; import type { ObservedEntityData } from '../shared/components/observed_entity/types'; import { useObservedUserItems } from './hooks/use_observed_user_items'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.tsx index e141779b559cf..8fb54478b3c4f 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.tsx @@ -10,6 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo } from 'react'; import { max } from 'lodash/fp'; import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { FlyoutHeader, FlyoutTitle } from '@kbn/security-solution-common'; import type { UserItem } from '../../../../common/search_strategy'; import { ManagedUserDatasetKey } from '../../../../common/search_strategy/security_solution/users/managed_details'; import { getUsersDetailsUrl } from '../../../common/components/link_to/redirect_to_users'; @@ -17,8 +18,6 @@ import type { ManagedUserData } from './types'; import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; import { PreferenceFormattedDate } from '../../../common/components/formatted_date'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; -import { FlyoutTitle } from '../../shared/components/flyout_title'; import type { ObservedEntityData } from '../shared/components/observed_entity/types'; interface UserPanelHeaderProps { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx index 6addcd92b6602..15ebee33010a0 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx @@ -8,6 +8,7 @@ import React, { useCallback, useMemo } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { FlyoutLoading, FlyoutNavigation } from '@kbn/security-solution-common/src/flyout'; import { useRefetchQueryById } from '../../../entity_analytics/api/hooks/use_refetch_query_by_id'; import type { Refetch } from '../../../common/types'; import { RISK_INPUTS_TAB_QUERY_ID } from '../../../entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab'; @@ -23,8 +24,6 @@ import { useGlobalTime } from '../../../common/containers/use_global_time'; import { AnomalyTableProvider } from '../../../common/components/ml/anomaly/anomaly_table_provider'; import { buildUserNamesFilter } from '../../../../common/search_strategy'; import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine'; -import { FlyoutLoading } from '../../shared/components/flyout_loading'; -import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; import { UserPanelContent } from './content'; import { UserPanelHeader } from './header'; import { UserDetailsPanelKey } from '../user_details_left'; diff --git a/x-pack/plugins/security_solution/public/flyout/network_details/content.tsx b/x-pack/plugins/security_solution/public/flyout/network_details/content.tsx index 8c9aa355ed43a..3634f73ef5a7f 100644 --- a/x-pack/plugins/security_solution/public/flyout/network_details/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/network_details/content.tsx @@ -8,8 +8,8 @@ import type { FC } from 'react'; import React, { memo } from 'react'; import { EuiSpacer } from '@elastic/eui'; +import { FlyoutBody } from '@kbn/security-solution-common'; import { NetworkDetails } from './components/network_details'; -import { FlyoutBody } from '../shared/components/flyout_body'; import type { FlowTargetSourceDest } from '../../../common/search_strategy'; export interface PanelContentProps { diff --git a/x-pack/plugins/security_solution/public/flyout/network_details/header.tsx b/x-pack/plugins/security_solution/public/flyout/network_details/header.tsx index 8ffceb345b1e0..1ef47c00689d9 100644 --- a/x-pack/plugins/security_solution/public/flyout/network_details/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/network_details/header.tsx @@ -9,11 +9,10 @@ import type { FC } from 'react'; import React, { memo, useMemo } from 'react'; import type { EuiFlyoutHeader } from '@elastic/eui'; import { SecurityPageName } from '@kbn/deeplinks-security'; +import { FlyoutHeader, FlyoutTitle } from '@kbn/security-solution-common'; import { getNetworkDetailsUrl } from '../../common/components/link_to'; import { SecuritySolutionLinkAnchor } from '../../common/components/links'; import type { FlowTargetSourceDest } from '../../../common/search_strategy'; -import { FlyoutHeader } from '../shared/components/flyout_header'; -import { FlyoutTitle } from '../shared/components/flyout_title'; import { encodeIpv6 } from '../../common/lib/helpers'; export interface PanelHeaderProps extends React.ComponentProps { diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/alert_preview_button.test.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/alert_preview_button.test.tsx index f478812f96f93..1d9358cb1bb31 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/alert_preview_button.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/alert_preview_button.test.tsx @@ -11,11 +11,14 @@ import React from 'react'; import { AlertPreviewButton } from './alert_preview_button'; import { DocumentDetailsPreviewPanelKey } from '../../document_details/shared/constants/panel_keys'; import { ALERT_PREVIEW_BANNER } from '../../document_details/preview/constants'; +import { createExpandableFlyoutApiMock } from '../../../common/mock/expandable_flyout'; const mockOpenPreviewPanel = jest.fn(); +const mockExpandableFlyoutApi = createExpandableFlyoutApiMock(); jest.mock('@kbn/expandable-flyout', () => { return { useExpandableFlyoutApi: () => ({ + ...mockExpandableFlyoutApi, openPreviewPanel: mockOpenPreviewPanel, }), }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx index 8a4f911468e4a..04cfeaff92d0b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx @@ -13,6 +13,8 @@ import { TestProviders } from '../../../common/mock'; import { TimelineId, TimelineTabs } from '../../../../common/types/timeline'; import { StatefulEventContext } from '../../../common/components/events_viewer/stateful_event_context'; import { NetworkPanelKey } from '../../../flyout/network_details'; +import { createExpandableFlyoutApiMock } from '../../../common/mock/expandable_flyout'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; jest.mock('react-redux', () => { const origin = jest.requireActual('react-redux'); @@ -46,13 +48,15 @@ jest.mock('../../../common/components/drag_and_drop/draggable_wrapper', () => { jest.mock('../../store'); const mockOpenFlyout = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => ({ - useExpandableFlyoutApi: () => ({ - openFlyout: mockOpenFlyout, - }), -})); +jest.mock('@kbn/expandable-flyout'); describe('FormattedIp', () => { + beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + ...createExpandableFlyoutApiMock(), + openFlyout: mockOpenFlyout, + }); + }); const props = { value: '192.168.1.1', contextId: 'test-context-id', diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx index 98d3ea8f507bb..9674b9146ecb0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx @@ -39,6 +39,8 @@ import type { } from '@hello-pangea/dnd'; import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/shared/constants/panel_keys'; import { createTelemetryServiceMock } from '../../../../common/lib/telemetry/telemetry_service.mock'; +import { createExpandableFlyoutApiMock } from '../../../../common/mock/expandable_flyout'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; jest.mock('../../../../common/hooks/use_app_toasts'); jest.mock('../../../../common/components/guided_onboarding_tour/tour_step'); @@ -99,11 +101,7 @@ jest.mock('react-redux', () => { }); const mockOpenFlyout = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ openFlyout: mockOpenFlyout }), - }; -}); +jest.mock('@kbn/expandable-flyout'); const mockedTelemetry = createTelemetryServiceMock(); @@ -236,6 +234,11 @@ describe('Body', () => { let appToastsMock: jest.Mocked>; beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + ...createExpandableFlyoutApiMock(), + openFlyout: mockOpenFlyout, + }); + mockUseCurrentUser.mockReturnValue({ username: 'test-username' }); mockUseKibana.mockReturnValue({ services: { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx index d00ad83b9b556..52344857a07c1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { type PropsWithChildren } from 'react'; +import React from 'react'; import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; @@ -14,18 +14,13 @@ import { TimelineId, TimelineTabs } from '../../../../../../common/types/timelin import { StatefulEventContext } from '../../../../../common/components/events_viewer/stateful_event_context'; import { createTelemetryServiceMock } from '../../../../../common/lib/telemetry/telemetry_service.mock'; import { TableId } from '@kbn/securitysolution-data-table'; +import { createExpandableFlyoutApiMock } from '../../../../../common/mock/expandable_flyout'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; const mockedTelemetry = createTelemetryServiceMock(); const mockOpenRightPanel = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ - openRightPanel: mockOpenRightPanel, - }), - TestProvider: ({ children }: PropsWithChildren<{}>) => <>{children}, - }; -}); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../../common/lib/kibana/kibana_react', () => { return { @@ -46,6 +41,13 @@ jest.mock('../../../../../common/components/draggables', () => ({ })); describe('HostName', () => { + beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + ...createExpandableFlyoutApiMock(), + openRightPanel: mockOpenRightPanel, + }); + }); + afterEach(() => { jest.clearAllMocks(); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.test.tsx index 471d43dcf8462..6c3dffc58ce25 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.test.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { type PropsWithChildren } from 'react'; +import React from 'react'; import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; @@ -14,18 +14,13 @@ import { UserName } from './user_name'; import { StatefulEventContext } from '../../../../../common/components/events_viewer/stateful_event_context'; import { createTelemetryServiceMock } from '../../../../../common/lib/telemetry/telemetry_service.mock'; import { TableId } from '@kbn/securitysolution-data-table'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { createExpandableFlyoutApiMock } from '../../../../../common/mock/expandable_flyout'; const mockedTelemetry = createTelemetryServiceMock(); const mockOpenRightPanel = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ - openRightPanel: mockOpenRightPanel, - }), - TestProvider: ({ children }: PropsWithChildren<{}>) => <>{children}, - }; -}); +jest.mock('@kbn/expandable-flyout'); jest.mock('../../../../../common/lib/kibana/kibana_react', () => { return { @@ -46,6 +41,12 @@ jest.mock('../../../../../common/components/draggables', () => ({ })); describe('UserName', () => { + beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue({ + ...createExpandableFlyoutApiMock(), + openRightPanel: mockOpenRightPanel, + }); + }); afterEach(() => { jest.clearAllMocks(); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx index 8b7b3742f0f27..973e0626aacc2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { ComponentProps, FunctionComponent, PropsWithChildren } from 'react'; +import type { ComponentProps, FunctionComponent } from 'react'; import React, { useEffect } from 'react'; import QueryTabContent from '.'; import { defaultRowRenderers } from '../../body/renderers'; @@ -35,6 +35,8 @@ import { defaultColumnHeaderType } from '../../body/column_headers/default_heade import { useUserPrivileges } from '../../../../../common/components/user_privileges'; import { getEndpointPrivilegesInitialStateMock } from '../../../../../common/components/user_privileges/endpoint/mocks'; import * as timelineActions from '../../../../store/actions'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { createExpandableFlyoutApiMock } from '../../../../../common/mock/expandable_flyout'; jest.mock('../../../../../common/components/user_privileges'); @@ -87,15 +89,7 @@ jest.mock(`@elastic/ebt/client`); const mockOpenFlyout = jest.fn(); const mockCloseFlyout = jest.fn(); -jest.mock('@kbn/expandable-flyout', () => { - return { - useExpandableFlyoutApi: () => ({ - openFlyout: mockOpenFlyout, - closeFlyout: mockCloseFlyout, - }), - TestProvider: ({ children }: PropsWithChildren<{}>) => <>{children}, - }; -}); +jest.mock('@kbn/expandable-flyout'); const TestComponent = (props: Partial>) => { const testComponentDefaultProps: ComponentProps = { @@ -162,6 +156,13 @@ let useTimelineEventsMock = jest.fn(); describe('query tab with unified timeline', () => { beforeAll(() => { // https://github.com/atlassian/react-beautiful-dnd/blob/4721a518356f72f1dac45b5fd4ee9d466aa2996b/docs/guides/setup-problem-detection-and-error-recovery.md#disable-logging + + jest.mocked(useExpandableFlyoutApi).mockImplementation(() => ({ + ...createExpandableFlyoutApiMock(), + openFlyout: mockOpenFlyout, + closeFlyout: mockCloseFlyout, + })); + Object.defineProperty(window, '__@hello-pangea/dnd-disable-dev-warnings', { get() { return true; diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 8ae0addf01d43..a2a9fda8ecc44 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -15,7 +15,11 @@ "public/**/*.json", "../../../typings/**/*" ], - "exclude": ["target/**/*", "**/cypress/**", "public/management/cypress.config.ts"], + "exclude": [ + "target/**/*", + "**/cypress/**", + "public/management/cypress.config.ts" + ], "kbn_references": [ "@kbn/core", { @@ -208,6 +212,7 @@ "@kbn/core-theme-browser", "@kbn/integration-assistant-plugin", "@kbn/avc-banner", + "@kbn/security-solution-common", "@kbn/esql-ast", "@kbn/esql-validation-autocomplete", "@kbn/config", diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 3b5a402334797..53dcc0869d477 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -6791,7 +6791,6 @@ "searchResponseWarnings.title.clustersClause": "Un problème est survenu avec {nonSuccessfulClustersCount} {nonSuccessfulClustersCount, plural, one {cluster} other {clusters}}", "searchResponseWarnings.title.clustersClauseAndRequestsClause": "{clustersClause} pour {requestsCount} requêtes", "searchResponseWarnings.viewDetailsButtonLabel": "Afficher les détails", - "securitySolutionPackages.alertAssignments.upsell": "Passer à {requiredLicense} pour utiliser les affectations d'alertes", "securitySolutionPackages.alertSuppressionRuleDetails.upsell": "La suppression d'alertes est configurée mais elle ne sera pas appliquée en raison d'une licence insuffisante", "securitySolutionPackages.alertSuppressionRuleForm.upsell": "La suppression d'alertes est activée avec la licence {requiredLicense} ou supérieure", "securitySolutionPackages.beta.label": "Bêta", @@ -39269,10 +39268,10 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "Voir un aperçu de l'alerte avec l'id {id}", "xpack.securitySolution.flyout.right.eventCategoryText": "Catégorie d'événement", "xpack.securitySolution.flyout.right.header.assignedTitle": "Utilisateurs affectés", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonAriaLabel": "Réduire les détails", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonLabel": "Réduire les détails", - "xpack.securitySolution.flyout.right.header.expandDetailButtonAriaLabel": "Développer les détails", - "xpack.securitySolution.flyout.right.header.expandDetailButtonLabel": "Développer les détails", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "Réduire les détails", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "Réduire les détails", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "Développer les détails", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "Développer les détails", "xpack.securitySolution.flyout.right.header.headerTitle": "Détails des documents", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "Aperçu", @@ -39359,10 +39358,10 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "à", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "Cette fonctionnalité requiert un {subscription}", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "Abonnement Enterprise", - "xpack.securitySolution.flyout.shared.errorDescription": "Une erreur est survenue lors de l'affichage de {message}.", - "xpack.securitySolution.flyout.shared.errorTitle": "Impossible d'afficher {title}.", - "xpack.securitySolution.flyout.shared.ExpandablePanelButtonIconAriaLabel": "Activer/Désactiver le panneau extensible", - "xpack.securitySolution.flyout.shared.expandablePanelLoadingAriaLabel": "panneau extensible", + "securitySolutionPackages.flyout.shared.errorDescription": "Une erreur est survenue lors de l'affichage de {message}.", + "securitySolutionPackages.flyout.shared.errorTitle": "Impossible d'afficher {title}.", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "Activer/Désactiver le panneau extensible", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "panneau extensible", "xpack.securitySolution.flyout.tour.entities.description": "Consultez la vue {entities} étendue pour en savoir plus sur les hôtes et les utilisateurs liés à l'alerte.", "xpack.securitySolution.flyout.tour.entities.text": "Entités", "xpack.securitySolution.flyout.tour.entities.title": "De nouvelles informations sur les hôtes et les utilisateurs sont disponibles", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f88fabd25833d..e89e452923f30 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -39251,10 +39251,10 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "ID {id}のアラートをプレビュー", "xpack.securitySolution.flyout.right.eventCategoryText": "イベントカテゴリ", "xpack.securitySolution.flyout.right.header.assignedTitle": "担当者", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonAriaLabel": "詳細を折りたたむ", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonLabel": "詳細を折りたたむ", - "xpack.securitySolution.flyout.right.header.expandDetailButtonAriaLabel": "詳細を展開", - "xpack.securitySolution.flyout.right.header.expandDetailButtonLabel": "詳細を展開", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "詳細を折りたたむ", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "詳細を折りたたむ", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "詳細を展開", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "詳細を展開", "xpack.securitySolution.flyout.right.header.headerTitle": "ドキュメント詳細", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "概要", @@ -39341,10 +39341,10 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "に", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "この機能には{subscription}が必要です", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "エンタープライズサブスクリプション", - "xpack.securitySolution.flyout.shared.errorDescription": "{message}の表示中にエラーが発生しました。", - "xpack.securitySolution.flyout.shared.errorTitle": "{title}を表示できません。", - "xpack.securitySolution.flyout.shared.ExpandablePanelButtonIconAriaLabel": "展開可能なパネルトグル", - "xpack.securitySolution.flyout.shared.expandablePanelLoadingAriaLabel": "展開可能なパネル", + "securitySolutionPackages.flyout.shared.errorDescription": "{message}の表示中にエラーが発生しました。", + "securitySolutionPackages.flyout.shared.errorTitle": "{title}を表示できません。", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "展開可能なパネルトグル", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "展開可能なパネル", "xpack.securitySolution.flyout.tour.entities.description": "アラートに関連付けられたホストとユーザーの詳細については、展開された{entities}ビューを確認してください。", "xpack.securitySolution.flyout.tour.entities.text": "エンティティ", "xpack.securitySolution.flyout.tour.entities.title": "新しいホストとユーザーのインサイトがあります", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2ae9e055b1f01..30cfd990ff4ee 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -39295,10 +39295,10 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "预览 ID 为 {id} 的告警", "xpack.securitySolution.flyout.right.eventCategoryText": "事件类别", "xpack.securitySolution.flyout.right.header.assignedTitle": "被分配人", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonAriaLabel": "折叠详情", - "xpack.securitySolution.flyout.right.header.collapseDetailButtonLabel": "折叠详情", - "xpack.securitySolution.flyout.right.header.expandDetailButtonAriaLabel": "展开详情", - "xpack.securitySolution.flyout.right.header.expandDetailButtonLabel": "展开详情", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "折叠详情", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "折叠详情", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "展开详情", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "展开详情", "xpack.securitySolution.flyout.right.header.headerTitle": "文档详情", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "概览", @@ -39384,10 +39384,10 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "处于", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "此功能需要{subscription}", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "企业级订阅", - "xpack.securitySolution.flyout.shared.errorDescription": "显示 {message} 时出现错误。", - "xpack.securitySolution.flyout.shared.errorTitle": "无法显示 {title}。", - "xpack.securitySolution.flyout.shared.ExpandablePanelButtonIconAriaLabel": "可展开面板切换按钮", - "xpack.securitySolution.flyout.shared.expandablePanelLoadingAriaLabel": "可展开面板", + "securitySolutionPackages.flyout.shared.errorDescription": "显示 {message} 时出现错误。", + "securitySolutionPackages.flyout.shared.errorTitle": "无法显示 {title}。", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "可展开面板切换按钮", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "可展开面板", "xpack.securitySolution.flyout.tour.entities.description": "请查阅展开的 {entities} 视图以了解与该告警有关的主机和用户的更多信息。", "xpack.securitySolution.flyout.tour.entities.text": "实体", "xpack.securitySolution.flyout.tour.entities.title": "有新主机和用户洞见可用", diff --git a/yarn.lock b/yarn.lock index 127cdf45ea4ae..15ae0b8e5fcee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6291,6 +6291,10 @@ version "0.0.0" uid "" +"@kbn/security-solution-common@link:x-pack/packages/security-solution/common": + version "0.0.0" + uid "" + "@kbn/security-solution-distribution-bar@link:x-pack/packages/security-solution/distribution_bar": version "0.0.0" uid "" From 32dd3730fa70acdb2e37918861c32537ffd2fc7e Mon Sep 17 00:00:00 2001 From: Jorge Sanz Date: Tue, 27 Aug 2024 11:06:15 +0200 Subject: [PATCH 23/38] [Maps] Fix text readability on map scale, attribution, and coordinate controls (#189639) ## Summary Fixes #128783 This PR fixes the visualization of the texts in Maps scale bar, attribution, and coordinate controls with a dark background. ## Context While checking on the scale bar component of the map I saw this SCSS mixin that seemed to be broken. Originally I thought on fixing the shadow but the readability of the text is not great for dark background (see 7f2a698f4401c9b22f5c526ad8cfaa7839e30282)

Adding a shadow | before | after | | :--:| :--:| |![2024-07-31_16-17](https://github.com/user-attachments/assets/23239b0d-826e-482e-ac67-fe7faa50d696) | ![2024-07-31_16-18](https://github.com/user-attachments/assets/dffe0873-86dd-46b3-877e-ff4f5ef92c32) |
So I decided to propose to fix this by adding a background as is usual in other platforms. ![image](https://github.com/user-attachments/assets/7a7d0d11-1cf6-4961-b872-a5247c930363) ![image](https://github.com/user-attachments/assets/2c3d893b-f380-4724-9ad5-93adb6ec9fb6) ![image](https://github.com/user-attachments/assets/1a9becbc-40b1-4631-8360-f2a1bfafc9c2) --- .../mb_map/scale_control/_index.scss | 5 +++-- .../right_side_controls/_mixins.scss | 10 ++++------ .../attribution_control/_attribution_control.scss | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss index 264dfe5e24843..28da88491f1cc 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss @@ -5,9 +5,10 @@ bottom: $euiSizeM; pointer-events: none; color: $euiTextColor; - border-left: 2px solid $euiTextColor; - border-bottom: 2px solid $euiTextColor; + border-left: 2px solid rgba($euiTextColor, .6); + border-bottom: 2px solid rgba($euiTextColor, .6); text-align: right; + @include mapOverlayIsTextOnly; } .mapScaleControlFullScreen { diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss b/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss index 97557f1312e86..640545c065418 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss @@ -1,8 +1,6 @@ @mixin mapOverlayIsTextOnly { - text-shadow: - 0 0 2px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade; + background-color: $euiPageBackgroundColor; + + padding-left: $euiSizeXS; + padding-right: $euiSizeXS; } diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss index e319535b4a45c..51c82fd7aa443 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss @@ -2,7 +2,6 @@ @include mapOverlayIsTextOnly; @include euiTextBreakWord; pointer-events: all; - padding-left: $euiSizeM; } .mapAttributionControl__fullScreen { From 8431033910e539c120064a47e01d4b343635e978 Mon Sep 17 00:00:00 2001 From: Achyut Jhunjhunwala Date: Tue, 27 Aug 2024 11:12:53 +0200 Subject: [PATCH 24/38] [Dataset Quality]Migrate telemetry tests and remove flyout code (#190584) ## Summary closes https://github.com/elastic/kibana/issues/184572 After the merge of the 1st [PR](https://github.com/elastic/kibana/pull/189532) around Flyout migration, this PR covers the remaining bits. - [x] Adding same telemetry to the page which was present in the flyout - [x] Create a Locator and use it in the Table to connect the main page with Details page - [x] Update locator in Unified Doc Viewer - [x] Migrate all kind of tests which were present for flyout to the page - [x] Remove everything which was once called Dataset Quality Flyout. - [x] Make build green - Yellow is also acceptable --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../observability/locators/dataset_quality.ts | 11 - .../locators/dataset_quality_details.ts | 43 ++ .../deeplinks/observability/locators/index.ts | 1 + .../logs_overview_degraded_fields.tsx | 68 +-- x-pack/plugins/data_quality/common/index.ts | 6 +- ...ct_dataset_quality_details_locator_path.ts | 50 ++ .../construct_dataset_quality_locator_path.ts | 3 +- .../dataset_quality_details_locator.ts | 31 ++ .../locators/dataset_quality_locator.ts | 4 +- .../data_quality/common/locators/index.ts | 7 +- ... dataset_quality_details_url_schema_v1.ts} | 0 .../dataset_quality_url_schema_v1.ts | 33 +- .../data_quality/common/url_schema/index.ts | 2 +- x-pack/plugins/data_quality/public/plugin.ts | 11 +- .../public/routes/dataset_quality/context.tsx | 7 - .../routes/dataset_quality/url_schema_v1.ts | 29 +- .../dataset_quality_details/url_schema_v1.ts | 2 + .../dataset_quality/table/columns.tsx | 73 +-- .../table/dataset_quality_details_link.tsx | 52 ++ .../table/degraded_docs_percentage_link.tsx | 13 +- .../dataset_quality/table/table.tsx | 8 +- .../dataset_quality_details.tsx | 11 +- .../details/fields_list.tsx | 7 +- .../dataset_quality_details/header.tsx | 23 +- .../index_not_found_prompt.tsx | 18 +- .../degraded_docs/degraded_docs_chart.tsx | 4 +- .../document_trends/degraded_docs/index.tsx | 16 +- .../overview/summary/panel.tsx | 5 +- .../components/flyout/dataset_summary.tsx | 65 --- .../degraded_docs_trend/degraded_docs.tsx | 113 ---- .../flyout/degraded_fields/columns.tsx | 61 --- .../degraded_fields/degraded_fields.tsx | 25 - .../flyout/degraded_fields/spark_plot.tsx | 101 ---- .../flyout/degraded_fields/table.tsx | 54 -- .../public/components/flyout/fields_list.tsx | 94 ---- .../public/components/flyout/flyout.tsx | 147 ----- .../flyout/flyout_summary/flyout_summary.tsx | 186 ------- .../flyout_summary/flyout_summary_header.tsx | 78 --- .../flyout_summary_kpi_item.tsx | 107 ---- .../flyout_summary/flyout_summary_kpis.tsx | 88 --- .../flyout_summary/get_summary_kpis.test.ts | 171 ------ .../flyout/flyout_summary/get_summary_kpis.ts | 167 ------ .../public/components/flyout/header.tsx | 102 ---- .../public/components/flyout/index.tsx | 8 - .../flyout/integration_actions_menu.tsx | 204 ------- .../components/flyout/integration_summary.tsx | 72 --- .../public/components/flyout/types.ts | 13 - .../dataset_quality/create_controller.ts | 8 +- .../dataset_quality/public_state.ts | 19 +- .../controller/dataset_quality/types.ts | 17 - .../dataset_quality_details/types.ts | 2 +- .../dataset_quality/public/hooks/index.ts | 7 +- .../hooks/use_dataset_details_telemetry.ts | 200 +++++++ .../use_dataset_quality_degraded_field.ts | 76 --- ...e_dataset_quality_details_redirect_link.ts | 188 ------- .../use_dataset_quality_details_state.ts | 16 +- ...ers.tsx => use_dataset_quality_filters.ts} | 0 .../hooks/use_dataset_quality_flyout.tsx | 69 --- .../hooks/use_dataset_quality_table.tsx | 43 +- .../public/hooks/use_dataset_telemetry.ts | 119 ++++ ...ded_docs.ts => use_degraded_docs_chart.ts} | 48 +- .../public/hooks/use_degraded_docs_chart.tsx | 224 -------- .../hooks/use_flyout_integration_actions.tsx | 104 ---- .../public/hooks/use_integration_actions.ts | 62 ++- .../public/hooks/use_redirect_link.ts | 13 +- .../hooks/use_redirect_link_telemetry.ts | 75 +++ ...summary_panel.tsx => use_summary_panel.ts} | 0 .../public/hooks/use_telemetry.tsx | 382 ------------- .../dataset_quality/public/plugin.tsx | 2 - .../public/services/telemetry/types.ts | 1 + .../src/defaults.ts | 15 - .../src/notifications.ts | 34 -- .../src/state_machine.ts | 517 +----------------- .../dataset_quality_controller/src/types.ts | 108 +--- .../translations/translations/fr-FR.json | 7 - .../translations/translations/ja-JP.json | 7 - .../translations/translations/zh-CN.json | 7 - ...y_flyout.ts => dataset_quality_details.ts} | 237 ++++---- .../dataset_quality_privileges.ts | 22 +- .../functional/apps/dataset_quality/index.ts | 2 +- .../page_objects/dataset_quality.ts | 208 +++---- ...y_flyout.ts => dataset_quality_details.ts} | 232 ++++---- .../observability/dataset_quality/index.ts | 2 +- 83 files changed, 1176 insertions(+), 4291 deletions(-) create mode 100644 packages/deeplinks/observability/locators/dataset_quality_details.ts create mode 100644 x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts create mode 100644 x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts rename x-pack/plugins/data_quality/common/url_schema/{dataset_quality_detils_url_schema_v1.ts => dataset_quality_details_url_schema_v1.ts} (100%) create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts rename x-pack/plugins/observability_solution/dataset_quality/public/hooks/{use_dataset_quality_filters.tsx => use_dataset_quality_filters.ts} (100%) delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts rename x-pack/plugins/observability_solution/dataset_quality/public/hooks/{use_degraded_docs.ts => use_degraded_docs_chart.ts} (80%) delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts rename x-pack/plugins/observability_solution/dataset_quality/public/hooks/{use_summary_panel.tsx => use_summary_panel.ts} (100%) delete mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx rename x-pack/test/functional/apps/dataset_quality/{dataset_quality_flyout.ts => dataset_quality_details.ts} (69%) rename x-pack/test_serverless/functional/test_suites/observability/dataset_quality/{dataset_quality_flyout.ts => dataset_quality_details.ts} (69%) diff --git a/packages/deeplinks/observability/locators/dataset_quality.ts b/packages/deeplinks/observability/locators/dataset_quality.ts index e30648e3f129c..9e04e10e9933e 100644 --- a/packages/deeplinks/observability/locators/dataset_quality.ts +++ b/packages/deeplinks/observability/locators/dataset_quality.ts @@ -23,14 +23,6 @@ type TimeRangeConfig = { refresh: RefreshInterval; }; -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -type DatasetConfig = { - rawName: string; - type: string; - name: string; - namespace: string; -}; - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Filters = { timeRange: TimeRangeConfig; @@ -38,7 +30,4 @@ type Filters = { export interface DataQualityLocatorParams extends SerializableRecord { filters?: Filters; - flyout?: { - dataset: DatasetConfig; - }; } diff --git a/packages/deeplinks/observability/locators/dataset_quality_details.ts b/packages/deeplinks/observability/locators/dataset_quality_details.ts new file mode 100644 index 0000000000000..6f51bbbfe7ce3 --- /dev/null +++ b/packages/deeplinks/observability/locators/dataset_quality_details.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { SerializableRecord } from '@kbn/utility-types'; + +export const DATA_QUALITY_DETAILS_LOCATOR_ID = 'DATA_QUALITY_DETAILS_LOCATOR'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type RefreshInterval = { + pause: boolean; + value: number; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type TimeRangeConfig = { + from: string; + to: string; + refresh: RefreshInterval; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type DegradedFieldsTable = { + page?: number; + rowsPerPage?: number; + sort?: { + field: string; + direction: 'asc' | 'desc'; + }; +}; + +export interface DataQualityDetailsLocatorParams extends SerializableRecord { + dataStream: string; + timeRange?: TimeRangeConfig; + breakdownField?: string; + degradedFields?: { + table?: DegradedFieldsTable; + }; +} diff --git a/packages/deeplinks/observability/locators/index.ts b/packages/deeplinks/observability/locators/index.ts index 67e79ecb577ea..48902c8f37cf4 100644 --- a/packages/deeplinks/observability/locators/index.ts +++ b/packages/deeplinks/observability/locators/index.ts @@ -7,6 +7,7 @@ */ export * from './dataset_quality'; +export * from './dataset_quality_details'; export * from './logs_explorer'; export * from './observability_logs_explorer'; export * from './observability_onboarding'; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx index 976ef71c6b647..2ff0d6a224af2 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx @@ -23,7 +23,10 @@ import { import { i18n } from '@kbn/i18n'; import { orderBy } from 'lodash'; import { getRouterLinkProps } from '@kbn/router-utils'; -import { DATA_QUALITY_LOCATOR_ID, DataQualityLocatorParams } from '@kbn/deeplinks-observability'; +import { + DATA_QUALITY_DETAILS_LOCATOR_ID, + DataQualityDetailsLocatorParams, +} from '@kbn/deeplinks-observability'; import { BrowserUrlService } from '@kbn/share-plugin/public'; import { getUnifiedDocViewerServices } from '../../plugin'; @@ -39,13 +42,6 @@ interface DegradedField { values: string[]; } -interface ParamsForLocator { - dataStreamType: string; - dataStreamName: string; - dataStreamNamespace: string; - rawName: string; -} - interface TableOptions { page: { index: number; @@ -117,7 +113,7 @@ export const LogsOverviewDegradedFields = ({ rawDoc }: { rawDoc: DataTableRecord const columns = getDegradedFieldsColumns(); const tableData = getDataFormattedForTable(ignoredFieldValues); - const paramsForLocator = getParamsForLocator(sourceFields); + const dataStream = getDataStreamRawName(sourceFields); const accordionId = useGeneratedHtmlId({ prefix: qualityIssuesAccordionTitle, @@ -194,9 +190,7 @@ export const LogsOverviewDegradedFields = ({ rawDoc }: { rawDoc: DataTableRecord buttonContent={accordionTitle} paddingSize="m" initialIsOpen={false} - extraAction={ - - } + extraAction={} data-test-subj="unifiedDocViewLogsOverviewDegradedFieldsAccordion" > { +): string | undefined => { if (sourceFields) { const dataStreamTypeArr = sourceFields['data_stream.type']; const dataStreamType = dataStreamTypeArr ? dataStreamTypeArr[0] : undefined; @@ -256,49 +250,35 @@ const getParamsForLocator = ( const dataStreamName = dataStreamNameArr ? dataStreamNameArr[0] : undefined; const dataStreamNamespaceArr = sourceFields['data_stream.namespace']; const dataStreamNamespace = dataStreamNamespaceArr ? dataStreamNamespaceArr[0] : undefined; - let rawName; + let dataStream; if (dataStreamType && dataStreamName && dataStreamNamespace) { - rawName = `${dataStreamType}-${dataStreamName}-${dataStreamNamespace}`; + dataStream = `${dataStreamType}-${dataStreamName}-${dataStreamNamespace}`; } - if (rawName) { - return { - dataStreamType, - dataStreamName, - dataStreamNamespace, - rawName, - }; - } + return dataStream; } }; const DatasetQualityLink = React.memo( ({ urlService, - paramsForLocator, + dataStream, }: { urlService: BrowserUrlService; - paramsForLocator?: ParamsForLocator; + dataStream: string | undefined; }) => { - const locator = urlService.locators.get(DATA_QUALITY_LOCATOR_ID); - const locatorParams: DataQualityLocatorParams = paramsForLocator - ? { - flyout: { - dataset: { - rawName: paramsForLocator.rawName, - type: paramsForLocator.dataStreamType, - name: paramsForLocator.dataStreamName, - namespace: paramsForLocator.dataStreamNamespace, - }, - }, - } - : {}; - - const datasetQualityUrl = locator?.getRedirectUrl(locatorParams); + if (!dataStream) { + return null; + } + const locator = urlService.locators.get( + DATA_QUALITY_DETAILS_LOCATOR_ID + ); + + const datasetQualityUrl = locator?.getRedirectUrl({ dataStream }); const navigateToDatasetQuality = () => { - locator?.navigate(locatorParams); + locator?.navigate({ dataStream }); }; const datasetQualityLinkProps = getRouterLinkProps({ @@ -306,7 +286,7 @@ const DatasetQualityLink = React.memo( onClick: navigateToDatasetQuality, }); - return paramsForLocator ? ( + return ( {datasetQualityLinkTitle} - ) : null; + ); } ); diff --git a/x-pack/plugins/data_quality/common/index.ts b/x-pack/plugins/data_quality/common/index.ts index 1b174a9efe524..a1869cd9ac356 100644 --- a/x-pack/plugins/data_quality/common/index.ts +++ b/x-pack/plugins/data_quality/common/index.ts @@ -12,4 +12,8 @@ export const PLUGIN_NAME = i18n.translate('xpack.dataQuality.name', { defaultMessage: 'Data Set Quality', }); -export { DATA_QUALITY_URL_STATE_KEY, datasetQualityUrlSchemaV1 } from './url_schema'; +export { + DATA_QUALITY_URL_STATE_KEY, + datasetQualityUrlSchemaV1, + datasetQualityDetailsUrlSchemaV1, +} from './url_schema'; diff --git a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts new file mode 100644 index 0000000000000..31ae8591bb5b8 --- /dev/null +++ b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts @@ -0,0 +1,50 @@ +/* + * 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 { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; +import { ManagementAppLocatorParams } from '@kbn/management-plugin/common/locator'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { DataQualityDetailsLocatorParams } from '@kbn/deeplinks-observability'; +import { datasetQualityDetailsUrlSchemaV1, DATA_QUALITY_URL_STATE_KEY } from '../url_schema'; +import { deepCompactObject } from '../utils/deep_compact_object'; + +interface LocatorPathConstructionParams { + locatorParams: DataQualityDetailsLocatorParams; + useHash: boolean; + managementLocator: LocatorPublic; +} + +export const constructDatasetQualityDetailsLocatorPath = async ( + params: LocatorPathConstructionParams +) => { + const { locatorParams, useHash, managementLocator } = params; + + const pageState = datasetQualityDetailsUrlSchemaV1.urlSchemaRT.encode( + deepCompactObject({ + v: 1, + ...locatorParams, + }) + ); + + const managementPath = await managementLocator.getLocation({ + sectionId: 'data', + appId: 'data_quality/details', + }); + + const path = setStateToKbnUrl( + DATA_QUALITY_URL_STATE_KEY, + pageState, + { useHash, storeInHashQuery: false }, + `${managementPath.app}${managementPath.path}` + ); + + return { + app: '', + path, + state: {}, + }; +}; diff --git a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts index f5b5b0bf7ce59..4fc97618d33e1 100644 --- a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts +++ b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts @@ -20,7 +20,7 @@ interface LocatorPathConstructionParams { export const constructDatasetQualityLocatorPath = async (params: LocatorPathConstructionParams) => { const { - locatorParams: { filters, flyout }, + locatorParams: { filters }, useHash, managementLocator, } = params; @@ -29,7 +29,6 @@ export const constructDatasetQualityLocatorPath = async (params: LocatorPathCons deepCompactObject({ v: 1, filters, - flyout, }) ); diff --git a/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts b/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts new file mode 100644 index 0000000000000..a25e065b1efb4 --- /dev/null +++ b/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.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 type { LocatorDefinition } from '@kbn/share-plugin/public'; +import { + DataQualityDetailsLocatorParams, + DATA_QUALITY_DETAILS_LOCATOR_ID, +} from '@kbn/deeplinks-observability'; +import { DataQualityLocatorDependencies } from './types'; +import { constructDatasetQualityDetailsLocatorPath } from './construct_dataset_quality_details_locator_path'; + +export class DatasetQualityDetailsLocatorDefinition + implements LocatorDefinition +{ + public readonly id = DATA_QUALITY_DETAILS_LOCATOR_ID; + + constructor(protected readonly deps: DataQualityLocatorDependencies) {} + + public readonly getLocation = async (params: DataQualityDetailsLocatorParams) => { + const { useHash, managementLocator } = this.deps; + return await constructDatasetQualityDetailsLocatorPath({ + useHash, + managementLocator, + locatorParams: params, + }); + }; +} diff --git a/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts b/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts index 4bf804955b6bc..5db4980e4f661 100644 --- a/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts +++ b/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts @@ -5,13 +5,11 @@ * 2.0. */ -import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public'; +import type { LocatorDefinition } from '@kbn/share-plugin/public'; import { DataQualityLocatorParams, DATA_QUALITY_LOCATOR_ID } from '@kbn/deeplinks-observability'; import { DataQualityLocatorDependencies } from './types'; import { constructDatasetQualityLocatorPath } from './construct_dataset_quality_locator_path'; -export type DatasetQualityLocator = LocatorPublic; - export class DatasetQualityLocatorDefinition implements LocatorDefinition { diff --git a/x-pack/plugins/data_quality/common/locators/index.ts b/x-pack/plugins/data_quality/common/locators/index.ts index 97df9e70698d7..02d91cadb5fdb 100644 --- a/x-pack/plugins/data_quality/common/locators/index.ts +++ b/x-pack/plugins/data_quality/common/locators/index.ts @@ -5,11 +5,6 @@ * 2.0. */ -import { DatasetQualityLocator } from './dataset_quality_locator'; - export * from './dataset_quality_locator'; +export * from './dataset_quality_details_locator'; export * from './types'; - -export interface DataQualityLocators { - datasetQualityLocator: DatasetQualityLocator; -} diff --git a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_detils_url_schema_v1.ts b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_details_url_schema_v1.ts similarity index 100% rename from x-pack/plugins/data_quality/common/url_schema/dataset_quality_detils_url_schema_v1.ts rename to x-pack/plugins/data_quality/common/url_schema/dataset_quality_details_url_schema_v1.ts diff --git a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts index 78c4faeca8cd8..08313ddc4860b 100644 --- a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts +++ b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts @@ -6,37 +6,7 @@ */ import * as rt from 'io-ts'; -import { degradedFieldRT, tableRT, timeRangeRT } from './common'; - -const integrationRT = rt.strict({ - name: rt.string, - title: rt.string, - version: rt.string, -}); - -const datasetRT = rt.intersection([ - rt.strict({ - rawName: rt.string, - type: rt.string, - name: rt.string, - namespace: rt.string, - }), - rt.exact( - rt.partial({ - integration: integrationRT, - title: rt.string, - }) - ), -]); - -export const flyoutRT = rt.exact( - rt.partial({ - dataset: datasetRT, - insightsTimeRange: timeRangeRT, - breakdownField: rt.string, - degradedFields: degradedFieldRT, - }) -); +import { tableRT, timeRangeRT } from './common'; export const filtersRT = rt.exact( rt.partial({ @@ -54,7 +24,6 @@ export const urlSchemaRT = rt.exact( rt.partial({ v: rt.literal(1), table: tableRT, - flyout: flyoutRT, filters: filtersRT, }) ); diff --git a/x-pack/plugins/data_quality/common/url_schema/index.ts b/x-pack/plugins/data_quality/common/url_schema/index.ts index 0af03b6d503f5..bf984fa73f129 100644 --- a/x-pack/plugins/data_quality/common/url_schema/index.ts +++ b/x-pack/plugins/data_quality/common/url_schema/index.ts @@ -7,4 +7,4 @@ export { DATA_QUALITY_URL_STATE_KEY } from './common'; export * as datasetQualityUrlSchemaV1 from './dataset_quality_url_schema_v1'; -export * as datasetQualityDetailsUrlSchemaV1 from './dataset_quality_detils_url_schema_v1'; +export * as datasetQualityDetailsUrlSchemaV1 from './dataset_quality_details_url_schema_v1'; diff --git a/x-pack/plugins/data_quality/public/plugin.ts b/x-pack/plugins/data_quality/public/plugin.ts index cb217abf86fec..025268848a9a8 100644 --- a/x-pack/plugins/data_quality/public/plugin.ts +++ b/x-pack/plugins/data_quality/public/plugin.ts @@ -16,7 +16,10 @@ import { AppPluginSetupDependencies, } from './types'; import { PLUGIN_ID, PLUGIN_NAME } from '../common'; -import { DatasetQualityLocatorDefinition } from '../common/locators'; +import { + DatasetQualityLocatorDefinition, + DatasetQualityDetailsLocatorDefinition, +} from '../common/locators'; export class DataQualityPlugin implements @@ -67,6 +70,12 @@ export class DataQualityPlugin managementLocator, }) ); + share.url.locators.create( + new DatasetQualityDetailsLocatorDefinition({ + useHash, + managementLocator, + }) + ); } return {}; diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx b/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx index ddd3227fa1a2b..0614ab02db677 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx @@ -44,13 +44,6 @@ export function DatasetQualityContextProvider({ }); datasetQualityController.service.start(); - if (initialState?.flyout?.dataset) { - datasetQualityController.service.send({ - type: 'OPEN_FLYOUT', - dataset: initialState.flyout.dataset, - }); - } - setController(datasetQualityController); const datasetQualityStateSubscription = datasetQualityController.state$.subscribe((state) => { diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts b/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts index ee7fd8904a593..072acf88aa460 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - DatasetQualityFlyoutOptions, - DatasetQualityPublicStateUpdate, -} from '@kbn/dataset-quality-plugin/public/controller/dataset_quality'; +import { DatasetQualityPublicStateUpdate } from '@kbn/dataset-quality-plugin/public/controller/dataset_quality'; import * as rt from 'io-ts'; import { deepCompactObject } from '../../../common/utils/deep_compact_object'; import { datasetQualityUrlSchemaV1 } from '../../../common/url_schema'; @@ -18,7 +15,6 @@ export const getStateFromUrlValue = ( ): DatasetQualityPublicStateUpdate => deepCompactObject({ table: urlValue.table, - flyout: getFlyoutFromUrlValue(urlValue.flyout), filters: urlValue.filters, }); @@ -27,7 +23,6 @@ export const getUrlValueFromState = ( ): datasetQualityUrlSchemaV1.UrlSchema => deepCompactObject({ table: state.table, - flyout: state.flyout, filters: state.filters, v: 1, }); @@ -45,25 +40,3 @@ const stateFromUrlSchemaRT = new rt.Type< export const stateFromUntrustedUrlRT = datasetQualityUrlSchemaV1.urlSchemaRT.pipe(stateFromUrlSchemaRT); - -const getFlyoutFromUrlValue = ( - flyout?: datasetQualityUrlSchemaV1.UrlSchema['flyout'] -): DatasetQualityFlyoutOptions => - deepCompactObject({ - ...(flyout - ? { - ...flyout, - dataset: flyout.dataset - ? { - ...flyout.dataset, - integration: flyout.dataset.integration - ? { - ...flyout.dataset.integration, - datasets: {}, - } - : undefined, - } - : undefined, - } - : {}), - }); diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts b/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts index b97d1bb9100eb..551ae51892adf 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts @@ -17,6 +17,7 @@ export const getStateFromUrlValue = ( dataStream: urlValue.dataStream, timeRange: urlValue.timeRange, degradedFields: urlValue.degradedFields, + breakdownField: urlValue.breakdownField, }); export const getUrlValueFromState = ( @@ -26,6 +27,7 @@ export const getUrlValueFromState = ( dataStream: state.dataStream, timeRange: state.timeRange, degradedFields: state.degradedFields, + breakdownField: state.breakdownField, v: 1, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx index bea56c8957fa4..b18e20f5b22c4 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx @@ -14,7 +14,6 @@ import { EuiIcon, EuiLink, EuiToolTip, - EuiButtonIcon, EuiText, formatNumber, EuiSkeletonRectangle, @@ -25,27 +24,20 @@ import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import { css } from '@emotion/react'; +import { BrowserUrlService } from '@kbn/share-plugin/public'; import { DEGRADED_QUALITY_MINIMUM_PERCENTAGE, POOR_QUALITY_MINIMUM_PERCENTAGE, BYTE_NUMBER_FORMAT, } from '../../../../common/constants'; import { DataStreamStat } from '../../../../common/data_streams_stats/data_stream_stat'; -import { NavigationSource } from '../../../services/telemetry'; import { DatasetQualityIndicator, QualityIndicator } from '../../quality_indicator'; import { PrivilegesWarningIconWrapper, IntegrationIcon } from '../../common'; -import { useRedirectLink } from '../../../hooks'; -import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; +import { useDatasetRedirectLinkTelemetry, useRedirectLink } from '../../../hooks'; import { DegradedDocsPercentageLink } from './degraded_docs_percentage_link'; import { TimeRangeConfig } from '../../../../common/types'; +import { DatasetQualityDetailsLink } from './dataset_quality_details_link'; -const expandDatasetAriaLabel = i18n.translate('xpack.datasetQuality.expandLabel', { - defaultMessage: 'Expand', -}); -const collapseDatasetAriaLabel = i18n.translate('xpack.datasetQuality.collapseLabel', { - defaultMessage: 'Collapse', -}); const nameColumnName = i18n.translate('xpack.datasetQuality.nameColumnName', { defaultMessage: 'Data Set Name', }); @@ -162,52 +154,26 @@ export const getDatasetQualityTableColumns = ({ fieldFormats, canUserMonitorDataset, canUserMonitorAnyDataStream, - selectedDataset, - openFlyout, loadingDataStreamStats, loadingDegradedStats, showFullDatasetNames, isSizeStatsAvailable, isActiveDataset, timeRange, + urlService, }: { fieldFormats: FieldFormatsStart; canUserMonitorDataset: boolean; canUserMonitorAnyDataStream: boolean; - selectedDataset?: FlyoutDataset; loadingDataStreamStats: boolean; loadingDegradedStats: boolean; showFullDatasetNames: boolean; isSizeStatsAvailable: boolean; - openFlyout: (selectedDataset: FlyoutDataset) => void; isActiveDataset: (lastActivity: number) => boolean; timeRange: TimeRangeConfig; + urlService: BrowserUrlService; }): Array> => { return [ - { - name: '', - render: (dataStreamStat: DataStreamStat) => { - const isExpanded = dataStreamStat.rawName === selectedDataset?.rawName; - - return ( - openFlyout(dataStreamStat as FlyoutDataset)} - iconType={isExpanded ? 'minimize' : 'expand'} - title={!isExpanded ? expandDatasetAriaLabel : collapseDatasetAriaLabel} - aria-label={!isExpanded ? expandDatasetAriaLabel : collapseDatasetAriaLabel} - /> - ); - }, - width: '40px', - css: css` - &.euiTableCellContent { - padding: 0; - } - `, - }, { name: ( {nameColumnName} @@ -215,20 +181,22 @@ export const getDatasetQualityTableColumns = ({ field: 'title', sortable: true, render: (title: string, dataStreamStat: DataStreamStat) => { - const { integration, name } = dataStreamStat; + const { integration, name, rawName } = dataStreamStat; return ( - - - - - {title} - {showFullDatasetNames && ( - - {name} - - )} - + + + + + + {title} + {showFullDatasetNames && ( + + {name} + + )} + + ); }, }, @@ -382,9 +350,10 @@ const RedirectLink = ({ title: string; timeRange: TimeRangeConfig; }) => { + const { sendTelemetry } = useDatasetRedirectLinkTelemetry({ rawName: dataStreamStat.rawName }); const redirectLinkProps = useRedirectLink({ dataStreamStat, - telemetry: { page: 'main', navigationSource: NavigationSource.Table }, + sendTelemetry, timeRangeConfig: timeRange, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx new file mode 100644 index 0000000000000..ac73f269d9f5a --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx @@ -0,0 +1,52 @@ +/* + * 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 { BrowserUrlService } from '@kbn/share-plugin/public'; +import { + DATA_QUALITY_DETAILS_LOCATOR_ID, + DataQualityDetailsLocatorParams, +} from '@kbn/deeplinks-observability'; +import { getRouterLinkProps } from '@kbn/router-utils'; +import { EuiHeaderLink } from '@elastic/eui'; + +export const DatasetQualityDetailsLink = React.memo( + ({ + urlService, + dataStream, + children, + }: { + urlService: BrowserUrlService; + dataStream: string; + children: React.ReactNode; + }) => { + const locator = urlService.locators.get( + DATA_QUALITY_DETAILS_LOCATOR_ID + ); + const datasetQualityUrl = locator?.getRedirectUrl({ dataStream }); + const navigateToDatasetQuality = () => { + locator?.navigate({ dataStream }); + }; + + const datasetQualityLinkDetailsProps = getRouterLinkProps({ + href: datasetQualityUrl, + onClick: navigateToDatasetQuality, + }); + + return ( + + {children} + + ); + } +); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx index 54c393323ccfd..9d32c84891a34 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx @@ -8,8 +8,7 @@ import { EuiSkeletonRectangle, EuiFlexGroup, EuiLink } from '@elastic/eui'; import React from 'react'; import { _IGNORED } from '../../../../common/es_fields'; -import { NavigationSource } from '../../../services/telemetry'; -import { useRedirectLink } from '../../../hooks'; +import { useDatasetRedirectLinkTelemetry, useRedirectLink } from '../../../hooks'; import { QualityPercentageIndicator } from '../../quality_indicator'; import { DataStreamStat } from '../../../../common/data_streams_stats/data_stream_stat'; import { TimeRangeConfig } from '../../../../common/types'; @@ -27,13 +26,15 @@ export const DegradedDocsPercentageLink = ({ degradedDocs: { percentage, count }, } = dataStreamStat; + const { sendTelemetry } = useDatasetRedirectLinkTelemetry({ + rawName: dataStreamStat.rawName, + query: { language: 'kuery', query: `${_IGNORED}: *` }, + }); + const redirectLinkProps = useRedirectLink({ dataStreamStat, query: { language: 'kuery', query: `${_IGNORED}: *` }, - telemetry: { - page: 'main', - navigationSource: NavigationSource.Table, - }, + sendTelemetry, timeRangeConfig: timeRange, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx index 5bd8783fd0684..a7524198aa24a 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import React from 'react'; import { EuiBasicTable, EuiEmptyPrompt, @@ -14,8 +15,6 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { dynamic } from '@kbn/shared-ux-utility'; -import React from 'react'; import { fullDatasetNameDescription, fullDatasetNameLabel, @@ -27,8 +26,6 @@ import { import { useDatasetQualityTable } from '../../../hooks'; import { DescriptiveSwitch } from '../../common/descriptive_switch'; -const Flyout = dynamic(() => import('../../flyout/flyout')); - export const Table = () => { const { sort, @@ -38,8 +35,6 @@ export const Table = () => { columns, loading, resultsCount, - selectedDataset, - closeFlyout, showInactiveDatasets, showFullDatasetNames, canUserMonitorDataset, @@ -107,7 +102,6 @@ export const Table = () => { ) } /> - {selectedDataset && } ); }; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx index 522ad22fae429..56632cdad8cfa 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; -import { useDatasetQualityDetailsState } from '../../hooks'; +import { useDatasetDetailsTelemetry, useDatasetQualityDetailsState } from '../../hooks'; import { DataStreamNotFoundPrompt } from './index_not_found_prompt'; import { Header } from './header'; import { Overview } from './overview'; @@ -16,10 +16,15 @@ import { Details } from './details'; // eslint-disable-next-line import/no-default-export export default function DatasetQualityDetails() { const { isIndexNotFoundError, dataStream } = useDatasetQualityDetailsState(); + const { startTracking } = useDatasetDetailsTelemetry(); + + useEffect(() => { + startTracking(); + }, [startTracking]); return isIndexNotFoundError ? ( ) : ( - +
diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx index f48ad1d932357..f02b1720d9dfc 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx @@ -32,7 +32,12 @@ export function FieldsList({ {fields.map(({ fieldTitle, fieldValue, isLoading: isFieldLoading, actionsMenu }, index) => ( - + {fieldTitle} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx index 2a0e3e93e32ac..e45253b6405c8 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx @@ -18,19 +18,30 @@ import { import { css } from '@emotion/react'; import React from 'react'; import { openInDiscoverText, openInLogsExplorerText } from '../../../common/translations'; -import { useDatasetQualityDetailsRedirectLink, useDatasetQualityDetailsState } from '../../hooks'; +import { + useDatasetDetailsRedirectLinkTelemetry, + useDatasetDetailsTelemetry, + useDatasetQualityDetailsState, + useRedirectLink, +} from '../../hooks'; import { IntegrationIcon } from '../common'; export function Header() { const { datasetDetails, timeRange, integrationDetails, loadingState } = useDatasetQualityDetailsState(); + const { navigationSources } = useDatasetDetailsTelemetry(); + const { rawName, name: title } = datasetDetails; const euiShadow = useEuiShadow('s'); const { euiTheme } = useEuiTheme(); - const redirectLinkProps = useDatasetQualityDetailsRedirectLink({ + const { sendTelemetry } = useDatasetDetailsRedirectLinkTelemetry({ + navigationSource: navigationSources.Header, + }); + const redirectLinkProps = useRedirectLink({ dataStreamStat: datasetDetails, timeRangeConfig: timeRange, + sendTelemetry, }); const pageTitle = integrationDetails?.integration?.datasets?.[datasetDetails.name] ?? title; @@ -38,15 +49,15 @@ export function Header() { return !loadingState.integrationDetailsLoaded ? ( ) : ( - +

{pageTitle}

export function DataStreamNotFoundPrompt({ dataStream }: { dataStream: string }) { const promptTitle =

{emptyPromptTitle}

; - const promptBody =

{emptyPromptBody(dataStream)}

; + const promptBody = ( + +

{emptyPromptBody(dataStream)}

+
+ ); - return ; + return ( + + ); } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx index ff311032fe69f..3040e81f0e587 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx @@ -14,7 +14,7 @@ import { KibanaErrorBoundary } from '@kbn/shared-ux-error-boundary'; import { flyoutDegradedDocsTrendText } from '../../../../../../common/translations'; import { useKibanaContextForPlugin } from '../../../../../utils'; import { TimeRangeConfig } from '../../../../../../common/types'; -import { useDegradedDocs } from '../../../../../hooks/use_degraded_docs'; +import { useDegradedDocsChart } from '../../../../../hooks'; const CHART_HEIGHT = 180; const DISABLED_ACTIONS = [ @@ -26,7 +26,7 @@ const DISABLED_ACTIONS = [ interface DegradedDocsChartProps extends Pick< - ReturnType, + ReturnType, 'attributes' | 'isChartLoading' | 'onChartLoading' | 'extraActions' > { timeRange: TimeRangeConfig; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx index 985a748e792b1..7c3aea15a6cf1 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx @@ -29,13 +29,15 @@ import { openInLogsExplorerText, overviewDegradedDocsText, } from '../../../../../../common/translations'; -import { useDegradedDocs } from '../../../../../hooks/use_degraded_docs'; import { DegradedDocsChart } from './degraded_docs_chart'; import { - useDatasetQualityDetailsRedirectLink, + useDatasetDetailsRedirectLinkTelemetry, useDatasetQualityDetailsState, + useDegradedDocsChart, + useRedirectLink, } from '../../../../../hooks'; import { _IGNORED } from '../../../../../../common/es_fields'; +import { NavigationSource } from '../../../../../services/telemetry'; const degradedDocsTooltip = ( { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/summary/panel.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/summary/panel.tsx index b40f563a4dff4..e03e0957b5a52 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/summary/panel.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/summary/panel.tsx @@ -10,6 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSkeletonTitle, EuiText } from ' import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; import { PrivilegesWarningIconWrapper } from '../../../common'; +import { notAvailableLabel } from '../../../../../common/translations'; const verticalRule = css` width: 1px; @@ -95,8 +96,8 @@ export function PanelIndicator({ <> {userHasPrivilege && ( - -

{value}

+ +

{userHasPrivilege ? value : notAvailableLabel}

)} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx deleted file mode 100644 index cb35e9c74d334..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx +++ /dev/null @@ -1,65 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import { DataStreamDetails, DataStreamSettings } from '../../../common/data_streams_stats'; -import { - datasetCreatedOnText, - flyoutDatasetDetailsText, - datasetLastActivityText, -} from '../../../common/translations'; -import { FieldsList, FieldsListLoading } from './fields_list'; - -interface DatasetSummaryProps { - fieldFormats: FieldFormatsStart; - dataStreamSettings?: DataStreamSettings; - dataStreamSettingsLoading: boolean; - dataStreamDetails?: DataStreamDetails; - dataStreamDetailsLoading: boolean; -} - -export function DatasetSummary({ - dataStreamSettings, - dataStreamSettingsLoading, - dataStreamDetails, - dataStreamDetailsLoading, - fieldFormats, -}: DatasetSummaryProps) { - const dataFormatter = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE, [ - ES_FIELD_TYPES.DATE, - ]); - const formattedLastActivity = dataStreamDetails?.lastActivity - ? dataFormatter.convert(dataStreamDetails?.lastActivity) - : '-'; - const formattedCreatedOn = dataStreamSettings?.createdOn - ? dataFormatter.convert(dataStreamSettings.createdOn) - : '-'; - - return ( - - ); -} - -export function DatasetSummaryLoading() { - return ; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx deleted file mode 100644 index 5335d5de8692d..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx +++ /dev/null @@ -1,113 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect, useState } from 'react'; -import { css } from '@emotion/react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiSpacer, - EuiTitle, - EuiToolTip, - EuiIcon, - EuiCode, - OnTimeChangeProps, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { UnifiedBreakdownFieldSelector } from '@kbn/unified-histogram-plugin/public'; -import type { DataViewField } from '@kbn/data-views-plugin/common'; -import { useDegradedDocsChart } from '../../../hooks'; - -import { DEFAULT_TIME_RANGE, DEFAULT_DATEPICKER_REFRESH } from '../../../../common/constants'; -import { overviewDegradedDocsText } from '../../../../common/translations'; -import { DegradedDocsChart } from '../../dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function DegradedDocs({ - dataStream, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, - lastReloadTime, - onTimeRangeChange, -}: { - dataStream?: string; - timeRange?: TimeRangeConfig; - lastReloadTime: number; - onTimeRangeChange: (props: Pick) => void; -}) { - const { dataView, breakdown, ...chartProps } = useDegradedDocsChart({ dataStream }); - - const [breakdownDataViewField, setBreakdownDataViewField] = useState( - undefined - ); - - useEffect(() => { - if (breakdown.dataViewField && breakdown.fieldSupportsBreakdown) { - setBreakdownDataViewField(breakdown.dataViewField); - } else { - setBreakdownDataViewField(undefined); - } - - if (breakdown.dataViewField && !breakdown.fieldSupportsBreakdown) { - // TODO: If needed, notify user that the field is not breakable - } - }, [setBreakdownDataViewField, breakdown]); - - return ( - - - - -
{overviewDegradedDocsText}
-
- - - -
- - - - -
- - - - -
- ); -} - -const degradedDocsTooltip = ( - - _ignored - - ), - }} - /> -); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx deleted file mode 100644 index 1d7e79b3c0b36..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx +++ /dev/null @@ -1,61 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiBasicTableColumn } from '@elastic/eui'; -import { FieldFormat } from '@kbn/field-formats-plugin/common'; -import { formatNumber } from '@elastic/eui'; - -import { DegradedField } from '../../../../common/api_types'; -import { SparkPlot } from './spark_plot'; -import { NUMBER_FORMAT } from '../../../../common/constants'; - -const fieldColumnName = i18n.translate('xpack.datasetQuality.flyout.degradedField.field', { - defaultMessage: 'Field', -}); - -const countColumnName = i18n.translate('xpack.datasetQuality.flyout.degradedField.count', { - defaultMessage: 'Docs count', -}); - -const lastOccurrenceColumnName = i18n.translate( - 'xpack.datasetQuality.flyout.degradedField.lastOccurrence', - { - defaultMessage: 'Last occurrence', - } -); - -export const getDegradedFieldsColumns = ({ - dateFormatter, - isLoading, -}: { - dateFormatter: FieldFormat; - isLoading: boolean; -}): Array> => [ - { - name: fieldColumnName, - field: 'name', - }, - { - name: countColumnName, - sortable: true, - field: 'count', - render: (_, { count, timeSeries }) => { - const countValue = formatNumber(count, NUMBER_FORMAT); - return ; - }, - }, - { - name: lastOccurrenceColumnName, - sortable: true, - field: 'lastOccurrence', - render: (lastOccurrence: number) => { - return dateFormatter.convert(lastOccurrence); - }, - }, -]; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx deleted file mode 100644 index bd2c20b24171a..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx +++ /dev/null @@ -1,25 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiPanel, EuiTitle, EuiIconTip } from '@elastic/eui'; -import { flyoutImprovementText, flyoutImprovementTooltip } from '../../../../common/translations'; -import { DegradedFieldTable } from './table'; - -export function DegradedFields() { - return ( - - - -
{flyoutImprovementText}
-
- -
- -
- ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx deleted file mode 100644 index 964c3ee434f45..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx +++ /dev/null @@ -1,101 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiLoadingChart, - euiPaletteColorBlind, - useEuiTheme, -} from '@elastic/eui'; -import React from 'react'; -import { ScaleType, Settings, Tooltip, Chart, BarSeries } from '@elastic/charts'; -import { i18n } from '@kbn/i18n'; -import { Coordinate } from '../../../../common/types'; - -export function SparkPlot({ - valueLabel, - isLoading, - series, -}: { - valueLabel: React.ReactNode; - isLoading: boolean; - series?: Coordinate[] | null; -}) { - return ( - - - - - {valueLabel} - - ); -} - -function SparkPlotItem({ - isLoading, - series, -}: { - isLoading: boolean; - series?: Coordinate[] | null; -}) { - const { euiTheme } = useEuiTheme(); - const chartSize = { - height: euiTheme.size.l, - width: '80px', - }; - - const commonStyle = { - ...chartSize, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }; - const palette = euiPaletteColorBlind({ rotations: 2 }); - - if (isLoading) { - return ( -
- -
- ); - } - - if (hasValidTimeSeries(series)) { - return ( -
- - - - - -
- ); - } - - return ( -
- -
- ); -} - -function hasValidTimeSeries(series?: Coordinate[] | null): series is Coordinate[] { - return !!series?.some((point) => point.y !== 0); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx deleted file mode 100644 index 1a1baa8aae7cd..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx +++ /dev/null @@ -1,54 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiBasicTable, EuiEmptyPrompt } from '@elastic/eui'; -import React from 'react'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import { useDatasetQualityDegradedField } from '../../../hooks'; -import { getDegradedFieldsColumns } from './columns'; -import { - overviewDegradedFieldsTableLoadingText, - overviewDegradedFieldsTableNoData, -} from '../../../../common/translations'; - -export const DegradedFieldTable = () => { - const { isLoading, pagination, renderedItems, onTableChange, sort, fieldFormats } = - useDatasetQualityDegradedField(); - const dateFormatter = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE, [ - ES_FIELD_TYPES.DATE, - ]); - const columns = getDegradedFieldsColumns({ dateFormatter, isLoading }); - - return ( - {overviewDegradedFieldsTableNoData}

} - hasBorder={false} - titleSize="m" - /> - ) - } - /> - ); -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx deleted file mode 100644 index 1861d23b69a45..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx +++ /dev/null @@ -1,94 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode, Fragment } from 'react'; -import { - EuiFlexGroup, - EuiPanel, - EuiFlexItem, - EuiSpacer, - EuiTitle, - EuiHorizontalRule, - EuiSkeletonTitle, - EuiSkeletonText, - EuiSkeletonRectangle, -} from '@elastic/eui'; - -export function FieldsList({ - title, - fields, - actionsMenu: ActionsMenu, - dataTestSubj = `datasetQualityFlyoutFieldsList-${title.toLowerCase().split(' ').join('_')}`, -}: { - title: string; - fields: Array<{ fieldTitle: string; fieldValue: ReactNode; isLoading: boolean }>; - actionsMenu?: ReactNode; - dataTestSubj?: string; -}) { - return ( - - - - {title} - - {ActionsMenu} - - - - {fields.map(({ fieldTitle, fieldValue, isLoading: isFieldLoading }, index) => ( - - - - - {fieldTitle} - - - - - {fieldValue} - - - - - {index < fields.length - 1 ? : null} - - ))} - - - ); -} - -export function FieldsListLoading() { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx deleted file mode 100644 index cb6944057a2d6..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx +++ /dev/null @@ -1,147 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, useEffect } from 'react'; -import { css } from '@emotion/react'; -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiSpacer, - EuiHorizontalRule, - EuiPanel, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { dynamic } from '@kbn/shared-ux-utility'; -import { flyoutCancelText } from '../../../common/translations'; -import { useDatasetQualityFlyout, useDatasetDetailsTelemetry } from '../../hooks'; -import { DatasetSummary, DatasetSummaryLoading } from './dataset_summary'; -import { Header } from './header'; -import { FlyoutProps } from './types'; -import { BasicDataStream } from '../../../common/types'; - -const FlyoutSummary = dynamic(() => import('./flyout_summary/flyout_summary')); -const IntegrationSummary = dynamic(() => import('./integration_summary')); - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function Flyout({ dataset, closeFlyout }: FlyoutProps) { - const { - dataStreamStat, - dataStreamSettings, - dataStreamDetails, - isNonAggregatable, - fieldFormats, - timeRange, - loadingState, - flyoutLoading, - integration, - } = useDatasetQualityFlyout(); - - const linkDetails: BasicDataStream = { - name: dataset.name, - rawName: dataset.rawName, - integration: integration?.integrationDetails, - type: dataset.type, - namespace: dataset.namespace, - }; - - const title = integration?.integrationDetails?.datasets?.[dataset.name] ?? dataset.name; - - const { startTracking } = useDatasetDetailsTelemetry(); - - useEffect(() => { - startTracking(); - }, [startTracking]); - - return ( - - {flyoutLoading ? ( - - ) : ( - <> -
- - - - - - - - - {loadingState.dataStreamDetailsLoading && loadingState.dataStreamSettingsLoading ? ( - - ) : dataStreamStat ? ( - - - - {integration?.integrationDetails && ( - <> - - - - )} - - ) : null} - - - - - - - - {flyoutCancelText} - - - - - - )} - - ); -} - -const flyoutBodyStyles = css` - .euiFlyoutBody__overflowContent { - padding: 0; - } -`; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx deleted file mode 100644 index 5b89c43ad92d1..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx +++ /dev/null @@ -1,186 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - OnRefreshProps, - OnTimeChangeProps, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiCallOut, - EuiLink, - EuiCode, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n-react'; -import { DegradedDocs } from '../degraded_docs_trend/degraded_docs'; -import { DataStreamDetails } from '../../../../common/api_types'; -import { DEFAULT_TIME_RANGE, DEFAULT_DATEPICKER_REFRESH } from '../../../../common/constants'; -import { useDatasetQualityContext } from '../../dataset_quality/context'; -import { FlyoutSummaryHeader } from './flyout_summary_header'; -import { FlyoutSummaryKpis, FlyoutSummaryKpisLoading } from './flyout_summary_kpis'; -import { DegradedFields } from '../degraded_fields/degraded_fields'; -import { TimeRangeConfig } from '../../../../common/types'; -import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; - -const nonAggregatableWarningTitle = i18n.translate('xpack.datasetQuality.nonAggregatable.title', { - defaultMessage: 'Your request may take longer to complete', -}); - -const nonAggregatableWarningDescription = (dataset: string) => ( - - {dataset} - - ), - howToFixIt: ( - - {i18n.translate( - 'xpack.datasetQuality.flyout.nonAggregatableDatasets.link.title', - { - defaultMessage: 'rollover', - } - )} - - ), - }} - /> - ), - }} - /> - ), - }} - /> -); - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function FlyoutSummary({ - dataStream, - dataStreamStat, - dataStreamDetails, - isNonAggregatable, - dataStreamDetailsLoading, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, -}: { - dataStream: string; - dataStreamStat?: FlyoutDataset; - dataStreamDetails?: DataStreamDetails; - dataStreamDetailsLoading: boolean; - timeRange?: TimeRangeConfig; - isNonAggregatable?: boolean; -}) { - const { service } = useDatasetQualityContext(); - const [lastReloadTime, setLastReloadTime] = useState(Date.now()); - - const updateTimeRange = useCallback( - ({ start, end, refreshInterval }: OnRefreshProps) => { - service.send({ - type: 'UPDATE_INSIGHTS_TIME_RANGE', - timeRange: { - from: start, - to: end, - refresh: { ...DEFAULT_DATEPICKER_REFRESH, value: refreshInterval }, - }, - }); - }, - [service] - ); - - const handleTimeChange = useCallback( - ({ isInvalid, ...timeRangeProps }: OnTimeChangeProps) => { - if (!isInvalid) { - updateTimeRange({ refreshInterval: timeRange.refresh.value, ...timeRangeProps }); - } - }, - [updateTimeRange, timeRange.refresh] - ); - - const handleTimeRangeChange = useCallback( - ({ start, end }: Pick) => { - updateTimeRange({ start, end, refreshInterval: timeRange.refresh.value }); - }, - [updateTimeRange, timeRange.refresh] - ); - - const handleRefresh = useCallback( - (refreshProps: OnRefreshProps) => { - updateTimeRange(refreshProps); - setLastReloadTime(Date.now()); - }, - [updateTimeRange] - ); - - return ( - <> - {isNonAggregatable && ( - - - -

{nonAggregatableWarningDescription(dataStream)}

-
-
-
- )} - - - - - {dataStreamStat ? ( - - ) : ( - - )} - - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx deleted file mode 100644 index c0ee7303b51a5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx +++ /dev/null @@ -1,78 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { css } from '@emotion/react'; -import { - EuiFlexGroup, - EuiIcon, - EuiSuperDatePicker, - EuiTitle, - EuiToolTip, - OnRefreshProps, - OnTimeChangeProps, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import { flyoutSummaryText } from '../../../../common/translations'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function FlyoutSummaryHeader({ - timeRange, - onTimeChange, - onRefresh, -}: { - timeRange: TimeRangeConfig; - onTimeChange: (timeChangeProps: OnTimeChangeProps) => void; - onRefresh: (refreshProps: OnRefreshProps) => void; -}) { - return ( - - - - {flyoutSummaryText} - - - - - - - - - - - ); -} - -const flyoutSummaryTooltip = ( - -); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx deleted file mode 100644 index 767cd8ec41f4f..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx +++ /dev/null @@ -1,107 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiTitle, - EuiText, - EuiLink, - useEuiTheme, - EuiSkeletonTitle, - EuiSkeletonRectangle, -} from '@elastic/eui'; - -import { PrivilegesWarningIconWrapper } from '../../common'; -import { notAvailableLabel } from '../../../../common/translations'; -import type { getSummaryKpis } from './get_summary_kpis'; - -export function FlyoutSummaryKpiItem({ - title, - value, - link, - isLoading, - userHasPrivilege, -}: ReturnType[number] & { isLoading: boolean }) { - const { euiTheme } = useEuiTheme(); - - return ( - - - - - -
{title}
-
- - - <> - -
- {link ? ( - - - {link.label} - - - ) : null} -
- - - -

{userHasPrivilege ? value : notAvailableLabel}

-
-
-
-
-
- ); -} - -export function FlyoutSummaryKpiItemLoading({ title }: { title: string }) { - return ( - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx deleted file mode 100644 index 47b41712dc7f5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx +++ /dev/null @@ -1,88 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import { _IGNORED } from '../../../../common/es_fields'; - -import { DataStreamDetails } from '../../../../common/api_types'; -import { useKibanaContextForPlugin } from '../../../utils'; -import { NavigationSource } from '../../../services/telemetry'; -import { useDatasetDetailsTelemetry, useRedirectLink } from '../../../hooks'; -import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; -import { FlyoutSummaryKpiItem, FlyoutSummaryKpiItemLoading } from './flyout_summary_kpi_item'; -import { getSummaryKpis } from './get_summary_kpis'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function FlyoutSummaryKpis({ - dataStreamStat, - dataStreamDetails, - isLoading, - timeRange, -}: { - dataStreamStat: FlyoutDataset; - dataStreamDetails?: DataStreamDetails; - isLoading: boolean; - timeRange: TimeRangeConfig; -}) { - const { - services: { observabilityShared }, - } = useKibanaContextForPlugin(); - const telemetry = useDatasetDetailsTelemetry(); - const hostsLocator = observabilityShared.locators.infra.hostsLocator; - - const degradedDocsLinkProps = useRedirectLink({ - dataStreamStat, - query: { language: 'kuery', query: `${_IGNORED}: *` }, - timeRangeConfig: timeRange, - telemetry: { - page: 'details', - navigationSource: NavigationSource.Summary, - }, - }); - - const kpis = useMemo( - () => - getSummaryKpis({ - dataStreamDetails, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }), - [dataStreamDetails, degradedDocsLinkProps, hostsLocator, telemetry, timeRange] - ); - - return ( - - - {kpis.map((kpi) => ( - - - - ))} - - - ); -} - -export function FlyoutSummaryKpisLoading() { - const telemetry = useDatasetDetailsTelemetry(); - - return ( - - - {getSummaryKpis({ telemetry }).map(({ title }) => ( - - - - ))} - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts deleted file mode 100644 index 28f5334e2f199..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts +++ /dev/null @@ -1,171 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { formatNumber } from '@elastic/eui'; -import type { useKibanaContextForPlugin } from '../../../utils'; -import type { useDatasetDetailsTelemetry } from '../../../hooks'; - -import { - BYTE_NUMBER_FORMAT, - DEFAULT_DATEPICKER_REFRESH, - DEFAULT_TIME_RANGE, - MAX_HOSTS_METRIC_VALUE, -} from '../../../../common/constants'; -import { - overviewDegradedDocsText, - flyoutDocsCountTotalText, - flyoutHostsText, - flyoutServicesText, - flyoutShowAllText, - flyoutSizeText, -} from '../../../../common/translations'; -import { getSummaryKpis } from './get_summary_kpis'; -import { TimeRangeConfig } from '../../../../common/types'; - -const dataStreamDetails = { - services: { - service1: ['service1Instance1', 'service1Instance2'], - service2: ['service2Instance1'], - }, - docsCount: 1000, - sizeBytes: 5000, - hosts: { - host1: ['host1Instance1', 'host1Instance2'], - host2: ['host2Instance1'], - }, - degradedDocsCount: 200, -}; - -const timeRange: TimeRangeConfig = { - ...DEFAULT_TIME_RANGE, - refresh: DEFAULT_DATEPICKER_REFRESH, - from: 'now-15m', - to: 'now', -}; - -const degradedDocsLinkProps = { - linkProps: { href: 'http://exploratory-view/degraded-docs', onClick: () => {} }, - navigate: () => {}, - isLogsExplorerAvailable: true, -}; -const hostsRedirectUrl = 'http://hosts/metric/'; - -const hostsLocator = { - getRedirectUrl: () => hostsRedirectUrl, -} as unknown as ReturnType< - typeof useKibanaContextForPlugin ->['services']['observabilityShared']['locators']['infra']['hostsLocator']; - -const telemetry = { - trackDetailsNavigated: () => {}, -} as unknown as ReturnType; - -describe('getSummaryKpis', () => { - it('should return the correct KPIs', () => { - const result = getSummaryKpis({ - dataStreamDetails, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }); - - expect(result).toEqual([ - { - title: flyoutDocsCountTotalText, - value: '1,000', - userHasPrivilege: true, - }, - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: false, - }, - { - title: flyoutServicesText, - value: '3', - link: undefined, - userHasPrivilege: true, - }, - { - title: flyoutHostsText, - value: '3', - link: undefined, - userHasPrivilege: true, - }, - { - title: overviewDegradedDocsText, - value: '200', - link: { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - }, - userHasPrivilege: true, - }, - ]); - }); - - it('show X+ if number of hosts or services exceed MAX_HOSTS_METRIC_VALUE', () => { - const services = { - service1: new Array(MAX_HOSTS_METRIC_VALUE + 1) - .fill('service1Instance') - .map((_, i) => `service1Instance${i}`), - }; - - const host3 = new Array(MAX_HOSTS_METRIC_VALUE + 1) - .fill('host3Instance') - .map((_, i) => `host3Instance${i}`); - - const detailsWithMaxPlusHosts = { - ...dataStreamDetails, - services, - hosts: { ...dataStreamDetails.hosts, host3 }, - }; - - const result = getSummaryKpis({ - dataStreamDetails: detailsWithMaxPlusHosts, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }); - - expect(result).toEqual([ - { - title: flyoutDocsCountTotalText, - value: '1,000', - userHasPrivilege: true, - }, - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: false, - }, - { - title: flyoutServicesText, - value: '50+', - link: undefined, - userHasPrivilege: true, - }, - { - title: flyoutHostsText, - value: '54+', - link: undefined, - userHasPrivilege: true, - }, - { - title: overviewDegradedDocsText, - value: '200', - link: { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - }, - userHasPrivilege: true, - }, - ]); - }); -}); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts deleted file mode 100644 index b574e1e8a8160..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts +++ /dev/null @@ -1,167 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { formatNumber } from '@elastic/eui'; -import { getRouterLinkProps, RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { - BYTE_NUMBER_FORMAT, - DEFAULT_DATEPICKER_REFRESH, - DEFAULT_TIME_RANGE, - MAX_HOSTS_METRIC_VALUE, - NUMBER_FORMAT, -} from '../../../../common/constants'; -import { - overviewDegradedDocsText, - flyoutDocsCountTotalText, - flyoutHostsText, - flyoutServicesText, - flyoutShowAllText, - flyoutSizeText, -} from '../../../../common/translations'; -import { DataStreamDetails } from '../../../../common/api_types'; -import { NavigationTarget, NavigationSource } from '../../../services/telemetry'; -import { useKibanaContextForPlugin } from '../../../utils'; -import type { useRedirectLink, useDatasetDetailsTelemetry } from '../../../hooks'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function getSummaryKpis({ - dataStreamDetails, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, - degradedDocsLinkProps, - hostsLocator, - telemetry, -}: { - dataStreamDetails?: DataStreamDetails; - timeRange?: TimeRangeConfig; - degradedDocsLinkProps?: ReturnType; - hostsLocator?: ReturnType< - typeof useKibanaContextForPlugin - >['services']['observabilityShared']['locators']['infra']['hostsLocator']; - telemetry: ReturnType; -}): Array<{ - title: string; - value: string; - link?: { label: string; props: RouterLinkProps }; - userHasPrivilege: boolean; -}> { - const services = dataStreamDetails?.services ?? {}; - const serviceKeys = Object.keys(services); - const countOfServices = serviceKeys - .map((key: string) => services[key].length) - .reduce((a, b) => a + b, 0); - - // @ts-ignore // TODO: Add link to APM services page when possible - https://github.com/elastic/kibana/issues/179904 - const servicesLink = { - label: flyoutShowAllText, - props: getRouterLinkProps({ - href: undefined, - onClick: () => { - telemetry.trackDetailsNavigated(NavigationTarget.Services, NavigationSource.Summary); - }, - }), - }; - - return [ - { - title: flyoutDocsCountTotalText, - value: formatNumber(dataStreamDetails?.docsCount ?? 0, NUMBER_FORMAT), - userHasPrivilege: true, - }, - // dataStreamDetails.sizeBytes = null indicates it's Serverless where `_stats` API isn't available - ...(dataStreamDetails?.sizeBytes !== null // Only show when not in Serverless - ? [ - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails?.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: Boolean(dataStreamDetails?.userPrivileges?.canMonitor), - }, - ] - : []), - { - title: flyoutServicesText, - value: formatMetricValueForMax(countOfServices, MAX_HOSTS_METRIC_VALUE, NUMBER_FORMAT), - link: undefined, - userHasPrivilege: true, - }, - getHostsKpi(dataStreamDetails?.hosts, timeRange, telemetry, hostsLocator), - { - title: overviewDegradedDocsText, - value: formatNumber(dataStreamDetails?.degradedDocsCount ?? 0, NUMBER_FORMAT), - link: - degradedDocsLinkProps && degradedDocsLinkProps.linkProps.href - ? { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - } - : undefined, - userHasPrivilege: true, - }, - ]; -} - -function getHostsKpi( - dataStreamHosts: DataStreamDetails['hosts'], - timeRange: TimeRangeConfig, - telemetry: ReturnType, - hostsLocator?: ReturnType< - typeof useKibanaContextForPlugin - >['services']['observabilityShared']['locators']['infra']['hostsLocator'] -) { - const hosts = dataStreamHosts ?? {}; - const hostKeys = Object.keys(hosts); - const countOfHosts = hostKeys - .map((key: string) => hosts[key].length) - .reduce( - ({ count, anyHostExceedsMax }, hostCount) => ({ - count: count + hostCount, - anyHostExceedsMax: anyHostExceedsMax || hostCount > MAX_HOSTS_METRIC_VALUE, - }), - { count: 0, anyHostExceedsMax: false } - ); - - // Create a query so from hostKeys so that (key: value OR key: value2) - const hostsKuery = hostKeys - .filter((key) => hosts[key].length > 0) - .map((key) => hosts[key].map((value) => `${key}: "${value}"`).join(' OR ')) - .join(' OR '); - const hostsUrl = hostsLocator?.getRedirectUrl({ - query: { language: 'kuery', query: hostsKuery }, - dateRange: { from: timeRange.from, to: timeRange.to }, - limit: countOfHosts.count, - }); - - // @ts-ignore // TODO: Add link to Infra Hosts page when possible - const hostsLink = { - label: flyoutShowAllText, - props: getRouterLinkProps({ - href: hostsUrl, - onClick: () => { - telemetry.trackDetailsNavigated(NavigationTarget.Hosts, NavigationSource.Summary); - }, - }), - }; - - return { - title: flyoutHostsText, - value: formatMetricValueForMax( - countOfHosts.anyHostExceedsMax ? countOfHosts.count + 1 : countOfHosts.count, - countOfHosts.count, - NUMBER_FORMAT - ), - link: undefined, - userHasPrivilege: true, - }; -} - -/** - * Formats a metric value to show a '+' sign if it's above a max value e.g. 50+ - */ -function formatMetricValueForMax(value: number, max: number, numberFormat: string): string { - const exceedsMax = value > max; - const valueToShow = exceedsMax ? max : value; - return `${formatNumber(valueToShow, numberFormat)}${exceedsMax ? '+' : ''}`; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx deleted file mode 100644 index 1117c7da12a1b..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx +++ /dev/null @@ -1,102 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiFlyoutHeader, - EuiSkeletonTitle, - EuiTitle, - useEuiShadow, - useEuiTheme, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import React from 'react'; -import { openInDiscoverText, openInLogsExplorerText } from '../../../common/translations'; -import { NavigationSource } from '../../services/telemetry'; -import { useRedirectLink } from '../../hooks'; -import { IntegrationIcon } from '../common'; -import { BasicDataStream, TimeRangeConfig } from '../../../common/types'; - -export function Header({ - linkDetails, - loading, - title, - timeRange, -}: { - linkDetails: BasicDataStream; - loading: boolean; - title: string; - timeRange: TimeRangeConfig; -}) { - const { integration } = linkDetails; - const euiShadow = useEuiShadow('s'); - const { euiTheme } = useEuiTheme(); - const redirectLinkProps = useRedirectLink({ - dataStreamStat: linkDetails, - telemetry: { - page: 'details', - navigationSource: NavigationSource.Header, - }, - timeRangeConfig: timeRange, - }); - - return ( - - {loading ? ( - - ) : ( - - - - -

{title}

-
-
- -
-
-
- - - - {redirectLinkProps.isLogsExplorerAvailable - ? openInLogsExplorerText - : openInDiscoverText} - - - -
- )} -
- ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx deleted file mode 100644 index 6a2c75f0054a7..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx +++ /dev/null @@ -1,8 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './flyout'; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx deleted file mode 100644 index 99afb7f269df5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx +++ /dev/null @@ -1,204 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButtonEmpty, - EuiButtonIcon, - EuiContextMenu, - EuiContextMenuPanelDescriptor, - EuiContextMenuPanelItemDescriptor, - EuiPopover, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { useDatasetQualityFlyout } from '../../hooks'; -import { useFlyoutIntegrationActions } from '../../hooks/use_flyout_integration_actions'; -import { Integration } from '../../../common/data_streams_stats/integration'; -import { Dashboard } from '../../../common/api_types'; - -const integrationActionsText = i18n.translate('xpack.datasetQuality.flyoutIntegrationActionsText', { - defaultMessage: 'Integration actions', -}); - -const seeIntegrationText = i18n.translate('xpack.datasetQuality.flyoutSeeIntegrationActionText', { - defaultMessage: 'See integration', -}); - -const indexTemplateText = i18n.translate('xpack.datasetQuality.flyoutIndexTemplateActionText', { - defaultMessage: 'Index template', -}); - -const viewDashboardsText = i18n.translate('xpack.datasetQuality.flyoutViewDashboardsActionText', { - defaultMessage: 'View dashboards', -}); - -export function IntegrationActionsMenu({ - integration, - dashboards, - dashboardsLoading, -}: { - integration: Integration; - dashboards: Dashboard[]; - dashboardsLoading: boolean; -}) { - const { dataStreamStat, canUserAccessDashboards, canUserViewIntegrations } = - useDatasetQualityFlyout(); - const { version, name: integrationName } = integration; - const { type, name } = dataStreamStat!; - const { - isOpen, - handleCloseMenu, - handleToggleMenu, - getIntegrationOverviewLinkProps, - getIndexManagementLinkProps, - getDashboardLinkProps, - } = useFlyoutIntegrationActions(); - - const actionButton = ( - - ); - - const MenuActionItem = ({ - dataTestSubject, - buttonText, - routerLinkProps, - iconType, - disabled = false, - }: { - dataTestSubject: string; - buttonText: string | React.ReactNode; - routerLinkProps: RouterLinkProps; - iconType: string; - disabled?: boolean; - }) => ( - - {buttonText} - - ); - - const panelItems = useMemo(() => { - const firstLevelItems: EuiContextMenuPanelItemDescriptor[] = [ - ...(canUserViewIntegrations - ? [ - { - renderItem: () => ( - - ), - }, - ] - : []), - { - renderItem: () => ( - - ), - }, - { - isSeparator: true, - key: 'sep', - }, - ]; - - if (dashboards.length && canUserAccessDashboards) { - firstLevelItems.push({ - icon: 'dashboardApp', - panel: 1, - name: viewDashboardsText, - 'data-test-subj': 'datasetQualityFlyoutIntegrationActionViewDashboards', - disabled: false, - }); - } else if (dashboardsLoading) { - firstLevelItems.push({ - icon: 'dashboardApp', - name: , - 'data-test-subj': 'datasetQualityFlyoutIntegrationActionDashboardsLoading', - disabled: true, - }); - } - - const panel: EuiContextMenuPanelDescriptor[] = [ - { - id: 0, - items: firstLevelItems, - }, - { - id: 1, - title: viewDashboardsText, - items: dashboards.map((dashboard) => { - return { - renderItem: () => ( - - ), - }; - }), - }, - ]; - - return panel; - }, [ - dashboards, - getDashboardLinkProps, - getIndexManagementLinkProps, - getIntegrationOverviewLinkProps, - integrationName, - name, - type, - version, - dashboardsLoading, - canUserAccessDashboards, - canUserViewIntegrations, - ]); - - return ( - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx deleted file mode 100644 index 53262c7821ce7..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx +++ /dev/null @@ -1,72 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiFlexGroup, EuiBadge, EuiText } from '@elastic/eui'; -import React from 'react'; -import { css } from '@emotion/react'; -import { - flyoutIntegrationDetailsText, - flyoutIntegrationNameText, - integrationVersionText, -} from '../../../common/translations'; -import { IntegrationIcon } from '../common'; -import { FieldsList } from './fields_list'; -import { IntegrationActionsMenu } from './integration_actions_menu'; -import { Integration } from '../../../common/data_streams_stats/integration'; -import { Dashboard } from '../../../common/api_types'; - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function IntegrationSummary({ - integration, - dashboards, - dashboardsLoading, -}: { - integration: Integration; - dashboards: Dashboard[]; - dashboardsLoading: boolean; -}) { - const { name, version } = integration; - - const integrationActionsMenu = ( - - ); - return ( - - - - {name} - - - ), - isLoading: false, - }, - { - fieldTitle: integrationVersionText, - fieldValue: version, - isLoading: false, - }, - ]} - /> - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts deleted file mode 100644 index 97d82b862428d..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts +++ /dev/null @@ -1,13 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FlyoutDataset } from '../../state_machines/dataset_quality_controller'; - -export interface FlyoutProps { - dataset: FlyoutDataset; - closeFlyout: () => void; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts index 7424e13b0f93c..ea4443a61a8ff 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts @@ -11,12 +11,10 @@ import equal from 'fast-deep-equal'; import { distinctUntilChanged, from, map } from 'rxjs'; import { interpret } from 'xstate'; import { IDataStreamsStatsClient } from '../../services/data_streams_stats'; -import { IDataStreamDetailsClient } from '../../services/data_stream_details'; import { createDatasetQualityControllerStateMachine, DEFAULT_CONTEXT, } from '../../state_machines/dataset_quality_controller'; -import { DatasetQualityStartDeps } from '../../types'; import { getContextFromPublicState, getPublicStateFromContext } from './public_state'; import { DatasetQualityController, DatasetQualityPublicStateUpdate } from './types'; @@ -24,13 +22,11 @@ type InitialState = DatasetQualityPublicStateUpdate; interface Dependencies { core: CoreStart; - plugins: DatasetQualityStartDeps; dataStreamStatsClient: IDataStreamsStatsClient; - dataStreamDetailsClient: IDataStreamDetailsClient; } export const createDatasetQualityControllerFactory = - ({ core, plugins, dataStreamStatsClient, dataStreamDetailsClient }: Dependencies) => + ({ core, dataStreamStatsClient }: Dependencies) => async ({ initialState = DEFAULT_CONTEXT, }: { @@ -40,10 +36,8 @@ export const createDatasetQualityControllerFactory = const machine = createDatasetQualityControllerStateMachine({ initialContext, - plugins, toasts: core.notifications.toasts, dataStreamStatsClient, - dataStreamDetailsClient, }); const service = interpret(machine, { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts index 1bf0088bc7a48..ea5ae63f97073 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DatasetTableSortField, DegradedFieldSortField } from '../../hooks'; +import { DatasetTableSortField } from '../../hooks'; import { DatasetQualityControllerContext, DEFAULT_CONTEXT, @@ -17,7 +17,6 @@ export const getPublicStateFromContext = ( ): DatasetQualityPublicState => { return { table: context.table, - flyout: context.flyout, filters: context.filters, }; }; @@ -36,22 +35,6 @@ export const getContextFromPublicState = ( } : DEFAULT_CONTEXT.table.sort, }, - flyout: { - ...DEFAULT_CONTEXT.flyout, - ...publicState.flyout, - degradedFields: { - table: { - ...DEFAULT_CONTEXT.flyout.degradedFields.table, - ...publicState.flyout?.degradedFields?.table, - sort: publicState.flyout?.degradedFields?.table?.sort - ? { - ...publicState.flyout.degradedFields.table.sort, - field: publicState.flyout.degradedFields.table.sort.field as DegradedFieldSortField, - } - : DEFAULT_CONTEXT.flyout.degradedFields.table.sort, - }, - }, - }, filters: { ...DEFAULT_CONTEXT.filters, ...publicState.filters, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts index decb7454bd193..81b2de0088a52 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts @@ -9,9 +9,7 @@ import { Observable } from 'rxjs'; import { DatasetQualityControllerStateService, WithFilters, - WithFlyoutOptions, WithTableOptions, - DegradedFields, } from '../../state_machines/dataset_quality_controller'; export interface DatasetQualityController { @@ -25,25 +23,10 @@ export type DatasetQualityTableOptions = Partial< Omit & { sort: TableSortOptions } >; -type DegradedFieldSortOptions = Omit & { field: string }; - -export type DatasetQualityDegradedFieldTableOptions = Partial< - Omit & { - sort: DegradedFieldSortOptions; - } ->; - -export type DatasetQualityFlyoutOptions = Partial< - Omit & { - degradedFields: { table?: DatasetQualityDegradedFieldTableOptions }; - } ->; - export type DatasetQualityFilterOptions = Partial; export interface DatasetQualityPublicState { table: DatasetQualityTableOptions; - flyout: DatasetQualityFlyoutOptions; filters: DatasetQualityFilterOptions; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts index 65ca53c073d42..b5a295a897bd5 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts @@ -28,7 +28,7 @@ export type DatasetQualityDetailsPublicState = WithDefaultControllerState; // a must and everything else can be optional. The table inside the // degradedFields must accept field property as string export type DatasetQualityDetailsPublicStateUpdate = Partial< - Pick + Pick > & { dataStream: string; } & { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts index 5c746e2f1177b..ad588fd0b673f 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts @@ -6,14 +6,13 @@ */ export * from './use_dataset_quality_table'; -export * from './use_dataset_quality_flyout'; export * from './use_degraded_docs_chart'; export * from './use_redirect_link'; export * from './use_summary_panel'; export * from './use_create_dataview'; -export * from './use_dataset_quality_degraded_field'; -export * from './use_telemetry'; +export * from './use_redirect_link_telemetry'; export * from './use_dataset_quality_details_state'; -export * from './use_dataset_quality_details_redirect_link'; export * from './use_degraded_fields'; export * from './use_integration_actions'; +export * from './use_dataset_telemetry'; +export * from './use_dataset_details_telemetry'; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts new file mode 100644 index 0000000000000..f613d3af7fdc4 --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts @@ -0,0 +1,200 @@ +/* + * 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 { useCallback, useEffect, useMemo } from 'react'; +import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; +import { getDateISORange } from '@kbn/timerange'; +import { useDatasetQualityDetailsState } from './use_dataset_quality_details_state'; +import { DatasetDetailsEbtProps, NavigationSource, NavigationTarget } from '../services/telemetry'; +import { BasicDataStream, TimeRangeConfig } from '../../common/types'; +import { DataStreamDetails } from '../../common/api_types'; +import { Integration } from '../../common/data_streams_stats/integration'; +import { mapPercentageToQuality } from '../../common/utils'; +import { MASKED_FIELD_PLACEHOLDER, UNKOWN_FIELD_PLACEHOLDER } from '../../common/constants'; + +export function useDatasetDetailsTelemetry() { + const { + telemetryClient, + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integrationDetails, + loadingState, + } = useDatasetQualityDetailsState(); + + const ebtProps = useMemo(() => { + if (dataStreamDetails && timeRange && !loadingState.dataStreamDetailsLoading) { + return getDatasetDetailsEbtProps({ + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integration: integrationDetails.integration, + }); + } + + return undefined; + }, [ + dataStreamDetails, + timeRange, + loadingState.dataStreamDetailsLoading, + datasetDetails, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integrationDetails.integration, + ]); + + const startTracking = useCallback(() => { + telemetryClient.startDatasetDetailsTracking(); + }, [telemetryClient]); + + // Report opening dataset details + useEffect(() => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if (datasetDetailsTrackingState === 'started' && ebtProps) { + telemetryClient.trackDatasetDetailsOpened(ebtProps); + } + }, [ebtProps, telemetryClient]); + + const trackDetailsNavigated = useCallback( + (target: NavigationTarget, source: NavigationSource, isDegraded = false) => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if ( + (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && + ebtProps + ) { + telemetryClient.trackDatasetDetailsNavigated({ + ...ebtProps, + filters: { + is_degraded: isDegraded, + }, + target, + source, + }); + } else { + throw new Error( + 'Cannot report dataset details navigation telemetry without required data and state' + ); + } + }, + [ebtProps, telemetryClient] + ); + + const trackDatasetDetailsBreakdownFieldChanged = useCallback(() => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if ( + (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && + ebtProps + ) { + telemetryClient.trackDatasetDetailsBreakdownFieldChanged({ + ...ebtProps, + breakdown_field: ebtProps.breakdown_field, + }); + } + }, [ebtProps, telemetryClient]); + + const wrapLinkPropsForTelemetry = useCallback( + ( + props: RouterLinkProps, + target: NavigationTarget, + source: NavigationSource, + isDegraded = false + ) => { + return { + ...props, + onClick: (event: Parameters[0]) => { + trackDetailsNavigated(target, source, isDegraded); + if (props.onClick) { + props.onClick(event); + } + }, + }; + }, + [trackDetailsNavigated] + ); + + return { + startTracking, + trackDetailsNavigated, + wrapLinkPropsForTelemetry, + navigationTargets: NavigationTarget, + navigationSources: NavigationSource, + trackDatasetDetailsBreakdownFieldChanged, + }; +} + +function getDatasetDetailsEbtProps({ + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integration, +}: { + datasetDetails: BasicDataStream; + dataStreamDetails: DataStreamDetails; + timeRange: TimeRangeConfig; + canUserViewIntegrations: boolean; + canUserAccessDashboards: boolean; + breakdownField?: string; + isNonAggregatable: boolean; + isBreakdownFieldEcs: boolean; + integration?: Integration; +}): DatasetDetailsEbtProps { + const indexName = datasetDetails.rawName; + const dataStream = { + dataset: datasetDetails.name, + namespace: datasetDetails.namespace, + type: datasetDetails.type, + }; + const degradedDocs = dataStreamDetails?.degradedDocsCount ?? 0; + const totalDocs = dataStreamDetails?.docsCount ?? 0; + const degradedPercentage = + totalDocs > 0 ? Number(((degradedDocs / totalDocs) * 100).toFixed(2)) : 0; + const health = mapPercentageToQuality(degradedPercentage); + const { startDate: from, endDate: to } = getDateISORange(timeRange); + + return { + index_name: indexName, + data_stream: dataStream, + privileges: { + can_monitor_data_stream: true, + can_view_integrations: canUserViewIntegrations, + can_view_dashboards: canUserAccessDashboards, + }, + data_stream_aggregatable: !isNonAggregatable, + data_stream_health: health, + from, + to, + degraded_percentage: degradedPercentage, + integration: integration?.name, + breakdown_field: breakdownField + ? isBreakdownFieldEcs === null + ? UNKOWN_FIELD_PLACEHOLDER + : getMaskedBreakdownField(breakdownField, isBreakdownFieldEcs) + : breakdownField, + }; +} + +function getMaskedBreakdownField(breakdownField: string, isBreakdownFieldEcs: boolean) { + return isBreakdownFieldEcs ? breakdownField : MASKED_FIELD_PLACEHOLDER; +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts deleted file mode 100644 index d92aa5be153f6..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts +++ /dev/null @@ -1,76 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { useSelector } from '@xstate/react'; -import { useCallback, useMemo } from 'react'; -import { orderBy } from 'lodash'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { DegradedField } from '../../common/data_streams_stats'; -import { SortDirection } from '../../common/types'; -import { - DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - DEFAULT_DEGRADED_FIELD_SORT_FIELD, -} from '../../common/constants'; -import { useKibanaContextForPlugin } from '../utils'; - -type DegradedFieldSortField = keyof DegradedField; - -// TODO: DELETE this hook in favour of new hook post migration -export function useDatasetQualityDegradedField() { - const { service } = useDatasetQualityContext(); - const { - services: { fieldFormats }, - } = useKibanaContextForPlugin(); - - const degradedFields = useSelector(service, (state) => state.context.flyout.degradedFields) ?? {}; - const { data, table } = degradedFields; - const { page, rowsPerPage, sort } = table; - - const pagination = { - pageIndex: page, - pageSize: rowsPerPage, - totalItemCount: data?.length ?? 0, - hidePerPageOptions: true, - }; - - const onTableChange = useCallback( - (options: { - page: { index: number; size: number }; - sort?: { field: DegradedFieldSortField; direction: SortDirection }; - }) => { - service.send({ - type: 'UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA', - degraded_field_criteria: { - page: options.page.index, - rowsPerPage: options.page.size, - sort: { - field: options.sort?.field || DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: options.sort?.direction || DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, - }, - }); - }, - [service] - ); - - const renderedItems = useMemo(() => { - const sortedItems = orderBy(data, sort.field, sort.direction); - return sortedItems.slice(page * rowsPerPage, (page + 1) * rowsPerPage); - }, [data, sort.field, sort.direction, page, rowsPerPage]); - - const isLoading = useSelector(service, (state) => - state.matches('flyout.initializing.dataStreamDegradedFields.fetching') - ); - - return { - isLoading, - pagination, - onTableChange, - renderedItems, - sort: { sort }, - fieldFormats, - }; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts deleted file mode 100644 index 3000d05aa34de..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts +++ /dev/null @@ -1,188 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SINGLE_DATASET_LOCATOR_ID, - type SingleDatasetLocatorParams, -} from '@kbn/deeplinks-observability'; -import { type DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; -import { type Query, type AggregateQuery, buildPhraseFilter } from '@kbn/es-query'; -import { getRouterLinkProps } from '@kbn/router-utils'; -import type { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import type { LocatorPublic } from '@kbn/share-plugin/common'; -import type { LocatorClient } from '@kbn/shared-ux-prompt-no-data-views-types'; -import { useKibanaContextForPlugin } from '../utils'; -import { BasicDataStream, TimeRangeConfig } from '../../common/types'; - -export const useDatasetQualityDetailsRedirectLink = ({ - dataStreamStat, - query, - timeRangeConfig, - breakdownField, -}: { - dataStreamStat: T; - query?: Query | AggregateQuery; - timeRangeConfig: TimeRangeConfig; - breakdownField?: string; -}) => { - const { - services: { share }, - } = useKibanaContextForPlugin(); - - const { from, to } = timeRangeConfig; - - const logsExplorerLocator = - share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); - - const config = logsExplorerLocator - ? buildLogsExplorerConfig({ - locator: logsExplorerLocator, - dataStreamStat, - query, - from, - to, - breakdownField, - }) - : buildDiscoverConfig({ - locatorClient: share.url.locators, - dataStreamStat, - query, - from, - to, - breakdownField, - }); - - return { - linkProps: { - ...config.routerLinkProps, - }, - navigate: config.navigate, - isLogsExplorerAvailable: !!logsExplorerLocator, - }; -}; - -const buildLogsExplorerConfig = ({ - locator, - dataStreamStat, - query, - from, - to, - breakdownField, -}: { - locator: LocatorPublic; - dataStreamStat: T; - query?: Query | AggregateQuery; - from: string; - to: string; - breakdownField?: string; -}): { - navigate: () => void; - routerLinkProps: RouterLinkProps; -} => { - const params: SingleDatasetLocatorParams = { - dataset: dataStreamStat.name, - timeRange: { - from, - to, - }, - integration: dataStreamStat.integration?.name, - query, - filterControls: { - namespace: { - mode: 'include', - values: [dataStreamStat.namespace], - }, - }, - breakdownField, - }; - - const urlToLogsExplorer = locator.getRedirectUrl(params); - - const navigateToLogsExplorer = () => { - locator.navigate(params) as Promise; - }; - - const logsExplorerLinkProps = getRouterLinkProps({ - href: urlToLogsExplorer, - onClick: navigateToLogsExplorer, - }); - - return { routerLinkProps: logsExplorerLinkProps, navigate: navigateToLogsExplorer }; -}; - -const buildDiscoverConfig = ({ - locatorClient, - dataStreamStat, - query, - from, - to, - breakdownField, -}: { - locatorClient: LocatorClient; - dataStreamStat: T; - query?: Query | AggregateQuery; - from: string; - to: string; - breakdownField?: string; -}): { - navigate: () => void; - routerLinkProps: RouterLinkProps; -} => { - const dataViewId = `${dataStreamStat.type}-${dataStreamStat.name}-*`; - const dataViewTitle = dataStreamStat.integration - ? `[${dataStreamStat.integration.title}] ${dataStreamStat.name}` - : `${dataViewId}`; - - const params: DiscoverAppLocatorParams = { - timeRange: { - from, - to, - }, - refreshInterval: { - pause: true, - value: 60000, - }, - dataViewId, - dataViewSpec: { - id: dataViewId, - title: dataViewTitle, - }, - query, - breakdownField, - columns: ['@timestamp', 'message'], - filters: [ - buildPhraseFilter( - { - name: 'data_stream.namespace', - type: 'string', - }, - dataStreamStat.namespace, - { - id: dataViewId, - title: dataViewTitle, - } - ), - ], - interval: 'auto', - sort: [['@timestamp', 'desc']], - }; - - const locator = locatorClient.get(DISCOVER_APP_LOCATOR); - - const urlToDiscover = locator?.getRedirectUrl(params); - - const navigateToDiscover = () => { - locator?.navigate(params) as Promise; - }; - - const discoverLinkProps = getRouterLinkProps({ - href: urlToDiscover, - onClick: navigateToDiscover, - }); - - return { routerLinkProps: discoverLinkProps, navigate: navigateToDiscover }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts index 4b0626f951580..146ff9e5aa413 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts @@ -15,7 +15,7 @@ import { BasicDataStream } from '../../common/types'; import { useKibanaContextForPlugin } from '../utils'; export const useDatasetQualityDetailsState = () => { - const { service } = useDatasetQualityDetailsContext(); + const { service, telemetryClient } = useDatasetQualityDetailsContext(); const { services: { fieldFormats }, @@ -36,6 +36,14 @@ export const useDatasetQualityDetailsState = () => { : false ); + const isBreakdownFieldAsserted = useSelector( + service, + (state) => + state.matches('initializing.checkBreakdownFieldIsEcs.done') && + breakdownField && + isBreakdownFieldEcs + ); + const dataStreamSettings = useSelector(service, (state) => state.matches('initializing.dataStreamSettings.initializeIntegrations') ? state.context.dataStreamSettings @@ -67,7 +75,9 @@ export const useDatasetQualityDetailsState = () => { ) ); - const canUserViewIntegrations = dataStreamSettings?.datasetUserPrivileges?.canViewIntegrations; + const canUserViewIntegrations = Boolean( + dataStreamSettings?.datasetUserPrivileges?.canViewIntegrations + ); const dataStreamDetails = useSelector(service, (state) => state.matches('initializing.dataStreamDetails.done') @@ -115,6 +125,7 @@ export const useDatasetQualityDetailsState = () => { return { service, + telemetryClient, fieldFormats, isIndexNotFoundError, dataStream, @@ -123,6 +134,7 @@ export const useDatasetQualityDetailsState = () => { dataStreamDetails, breakdownField, isBreakdownFieldEcs, + isBreakdownFieldAsserted, isNonAggregatable, timeRange, loadingState, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.ts similarity index 100% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.tsx rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.ts diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx deleted file mode 100644 index 0f9d7981e619c..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx +++ /dev/null @@ -1,69 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useSelector } from '@xstate/react'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { useKibanaContextForPlugin } from '../utils'; - -export const useDatasetQualityFlyout = () => { - const { - services: { fieldFormats }, - } = useKibanaContextForPlugin(); - - const { service } = useDatasetQualityContext(); - - const { - dataset: dataStreamStat, - dataStreamSettings, - datasetDetails: dataStreamDetails, - insightsTimeRange, - breakdownField, - isNonAggregatable, - integration, - } = useSelector(service, (state) => state.context.flyout) ?? {}; - - const { timeRange } = useSelector(service, (state) => state.context.filters); - - const loadingState = useSelector(service, (state) => ({ - dataStreamDetailsLoading: state.matches('flyout.initializing.dataStreamDetails.fetching'), - dataStreamSettingsLoading: state.matches('flyout.initializing.dataStreamSettings.fetching'), - datasetIntegrationDashboardLoading: state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.fetching' - ), - datasetIntegrationDone: state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDetails.done' - ), - })); - - const canUserAccessDashboards = useSelector( - service, - (state) => - !state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.unauthorized' - ) - ); - - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - - return { - dataStreamStat, - dataStreamSettings, - dataStreamDetails, - isNonAggregatable, - integration, - fieldFormats, - timeRange: insightsTimeRange ?? timeRange, - breakdownField, - loadingState, - flyoutLoading: !dataStreamStat, - canUserAccessDashboards, - canUserViewIntegrations, - }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx index b205a58dfb98f..3a3475eabeeda 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx @@ -14,7 +14,6 @@ import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat import { tableSummaryAllText, tableSummaryOfText } from '../../common/translations'; import { getDatasetQualityTableColumns } from '../components/dataset_quality/table/columns'; import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { FlyoutDataset } from '../state_machines/dataset_quality_controller'; import { useKibanaContextForPlugin } from '../utils'; import { filterInactiveDatasets, isActiveDataset } from '../utils/filter_inactive_datasets'; import { SortDirection } from '../../common/types'; @@ -30,7 +29,10 @@ const sortingOverrides: Partial<{ export const useDatasetQualityTable = () => { const { - services: { fieldFormats }, + services: { + fieldFormats, + share: { url }, + }, } = useKibanaContextForPlugin(); const { service } = useDatasetQualityContext(); @@ -61,8 +63,6 @@ export const useDatasetQualityTable = () => { } = useSelector(service, (state) => state.context.filters); const showInactiveDatasets = inactive || !canUserMonitorDataset; - const flyout = useSelector(service, (state) => state.context.flyout); - const loading = useSelector( service, (state) => @@ -89,33 +89,6 @@ export const useDatasetQualityTable = () => { [service] ); - const closeFlyout = useCallback(() => service.send({ type: 'CLOSE_FLYOUT' }), [service]); - const openFlyout = useCallback( - (selectedDataset: FlyoutDataset) => { - if (flyout?.dataset?.rawName === selectedDataset.rawName) { - service.send({ - type: 'CLOSE_FLYOUT', - }); - - return; - } - - if (!flyout?.insightsTimeRange) { - service.send({ - type: 'OPEN_FLYOUT', - dataset: selectedDataset, - }); - return; - } - - service.send({ - type: 'SELECT_NEW_DATASET', - dataset: selectedDataset, - }); - }, - [flyout?.dataset?.rawName, flyout?.insightsTimeRange, service] - ); - const isActive = useCallback( (lastActivity: number) => isActiveDataset({ lastActivity, timeRange }), [timeRange] @@ -127,27 +100,25 @@ export const useDatasetQualityTable = () => { fieldFormats, canUserMonitorDataset, canUserMonitorAnyDataStream, - selectedDataset: flyout?.dataset, - openFlyout, loadingDataStreamStats, loadingDegradedStats, showFullDatasetNames, isSizeStatsAvailable, isActiveDataset: isActive, timeRange, + urlService: url, }), [ fieldFormats, canUserMonitorDataset, canUserMonitorAnyDataStream, - flyout?.dataset, - openFlyout, loadingDataStreamStats, loadingDegradedStats, showFullDatasetNames, isSizeStatsAvailable, isActive, timeRange, + url, ] ); @@ -235,8 +206,6 @@ export const useDatasetQualityTable = () => { columns, loading, resultsCount, - closeFlyout, - selectedDataset: flyout?.dataset, showInactiveDatasets, showFullDatasetNames, canUserMonitorDataset, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts new file mode 100644 index 0000000000000..167ebd37fe81a --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts @@ -0,0 +1,119 @@ +/* + * 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 { useSelector } from '@xstate/react'; +import { useCallback } from 'react'; +import { getDateISORange } from '@kbn/timerange'; +import { useDatasetQualityContext } from '../components/dataset_quality/context'; +import { useDatasetQualityFilters } from './use_dataset_quality_filters'; +import { DataStreamStat } from '../../common/data_streams_stats'; +import { DatasetEbtProps, DatasetNavigatedEbtProps } from '../services/telemetry'; + +export function useDatasetTelemetry() { + const { service, telemetryClient } = useDatasetQualityContext(); + + // eslint-disable-next-line react-hooks/exhaustive-deps + const datasets = useSelector(service, (state) => state.context.datasets) ?? {}; + const nonAggregatableDatasets = useSelector( + service, + (state) => state.context.nonAggregatableDatasets + ); + const canUserViewIntegrations = useSelector( + service, + (state) => state.context.datasetUserPrivileges.canViewIntegrations + ); + const sort = useSelector(service, (state) => state.context.table.sort); + const appliedFilters = useDatasetQualityFilters(); + + const trackDatasetNavigated = useCallback<(rawName: string, isIgnoredFilter: boolean) => void>( + (rawName: string, isIgnoredFilter: boolean) => { + const foundDataset = datasets.find((dataset) => dataset.rawName === rawName); + if (foundDataset) { + const ebtProps = getDatasetEbtProps( + foundDataset, + sort, + appliedFilters, + nonAggregatableDatasets, + isIgnoredFilter, + canUserViewIntegrations + ); + telemetryClient.trackDatasetNavigated(ebtProps); + } else { + throw new Error( + `Cannot report dataset navigation telemetry for unknown dataset ${rawName}` + ); + } + }, + [ + sort, + appliedFilters, + canUserViewIntegrations, + datasets, + nonAggregatableDatasets, + telemetryClient, + ] + ); + + return { trackDatasetNavigated }; +} + +function getDatasetEbtProps( + dataset: DataStreamStat, + sort: { field: string; direction: 'asc' | 'desc' }, + filters: ReturnType, + nonAggregatableDatasets: string[], + isIgnoredFilter: boolean, + canUserViewIntegrations: boolean +): DatasetNavigatedEbtProps { + const { startDate: from, endDate: to } = getDateISORange(filters.timeRange); + const datasetEbtProps: DatasetEbtProps = { + index_name: dataset.rawName, + data_stream: { + dataset: dataset.name, + namespace: dataset.namespace, + type: dataset.type, + }, + data_stream_health: dataset.degradedDocs.quality, + data_stream_aggregatable: nonAggregatableDatasets.some( + (indexName) => indexName === dataset.rawName + ), + from, + to, + degraded_percentage: dataset.degradedDocs.percentage, + integration: dataset.integration?.name, + privileges: { + can_monitor_data_stream: dataset.userPrivileges?.canMonitor ?? true, + can_view_integrations: canUserViewIntegrations, + }, + }; + + const ebtFilters: DatasetNavigatedEbtProps['filters'] = { + is_degraded: isIgnoredFilter, + query_length: filters.selectedQuery?.length ?? 0, + integrations: { + total: filters.integrations.filter((item) => item.name !== 'none').length, + included: filters.integrations.filter((item) => item?.checked === 'on').length, + excluded: filters.integrations.filter((item) => item?.checked === 'off').length, + }, + namespaces: { + total: filters.namespaces.length, + included: filters.namespaces.filter((item) => item?.checked === 'on').length, + excluded: filters.namespaces.filter((item) => item?.checked === 'off').length, + }, + qualities: { + total: filters.qualities.length, + included: filters.qualities.filter((item) => item?.checked === 'on').length, + excluded: filters.qualities.filter((item) => item?.checked === 'off').length, + }, + }; + + return { + ...datasetEbtProps, + sort, + filters: ebtFilters, + }; +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts similarity index 80% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts index 7842fe81966f3..795700bfc9441 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useCallback, useState, useMemo, useEffect } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import type { Action } from '@kbn/ui-actions-plugin/public'; import { fieldSupportsBreakdown } from '@kbn/unified-histogram-plugin/public'; import { i18n } from '@kbn/i18n'; @@ -16,7 +16,9 @@ import { useCreateDataView } from './use_create_dataview'; import { useKibanaContextForPlugin } from '../utils'; import { useDatasetQualityDetailsState } from './use_dataset_quality_details_state'; import { getLensAttributes } from '../components/dataset_quality_details/overview/document_trends/degraded_docs/lens_attributes'; -import { useDatasetQualityDetailsRedirectLink } from './use_dataset_quality_details_redirect_link'; +import { useRedirectLink } from './use_redirect_link'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; +import { useDatasetDetailsRedirectLinkTelemetry } from './use_redirect_link_telemetry'; const exploreDataInLogsExplorerText = i18n.translate( 'xpack.datasetQuality.details.chartExploreDataInLogsExplorerText', @@ -39,13 +41,27 @@ const openInLensText = i18n.translate('xpack.datasetQuality.details.chartOpenInL const ACTION_EXPLORE_IN_LOGS_EXPLORER = 'ACTION_EXPLORE_IN_LOGS_EXPLORER'; const ACTION_OPEN_IN_LENS = 'ACTION_OPEN_IN_LENS'; -export const useDegradedDocs = () => { +export const useDegradedDocsChart = () => { const { euiTheme } = useEuiTheme(); const { services: { lens }, } = useKibanaContextForPlugin(); - const { service, dataStream, datasetDetails, timeRange, breakdownField, integrationDetails } = - useDatasetQualityDetailsState(); + const { + service, + dataStream, + datasetDetails, + timeRange, + breakdownField, + integrationDetails, + isBreakdownFieldAsserted, + } = useDatasetQualityDetailsState(); + + const { + trackDatasetDetailsBreakdownFieldChanged, + trackDetailsNavigated, + navigationTargets, + navigationSources, + } = useDatasetDetailsTelemetry(); const [isChartLoading, setIsChartLoading] = useState(undefined); const [attributes, setAttributes] = useState | undefined>( @@ -75,6 +91,10 @@ export const useDegradedDocs = () => { [service] ); + useEffect(() => { + if (isBreakdownFieldAsserted) trackDatasetDetailsBreakdownFieldChanged(); + }, [trackDatasetDetailsBreakdownFieldChanged, isBreakdownFieldAsserted]); + useEffect(() => { const dataStreamName = dataStream ?? DEFAULT_LOGS_DATA_VIEW; const datasetTitle = @@ -98,13 +118,21 @@ export const useDegradedDocs = () => { const openInLensCallback = useCallback(() => { if (attributes) { + trackDetailsNavigated(navigationTargets.Lens, navigationSources.Chart); lens.navigateToPrefilledEditor({ id: '', timeRange, attributes, }); } - }, [attributes, lens, timeRange]); + }, [ + attributes, + lens, + navigationSources.Chart, + navigationTargets.Lens, + timeRange, + trackDetailsNavigated, + ]); const getOpenInLensAction = useMemo(() => { return { @@ -126,11 +154,17 @@ export const useDegradedDocs = () => { }; }, [openInLensCallback]); - const redirectLinkProps = useDatasetQualityDetailsRedirectLink({ + const { sendTelemetry } = useDatasetDetailsRedirectLinkTelemetry({ + query: { language: 'kuery', query: '_ignored:*' }, + navigationSource: navigationSources.Chart, + }); + + const redirectLinkProps = useRedirectLink({ dataStreamStat: datasetDetails, query: { language: 'kuery', query: '_ignored:*' }, timeRangeConfig: timeRange, breakdownField: breakdownDataViewField?.name, + sendTelemetry, }); const getOpenInLogsExplorerAction = useMemo(() => { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx deleted file mode 100644 index 6840f2a4088a9..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx +++ /dev/null @@ -1,224 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useCallback, useState, useMemo, useEffect } from 'react'; -import { Action } from '@kbn/ui-actions-plugin/public'; -import { fieldSupportsBreakdown } from '@kbn/unified-histogram-plugin/public'; -import { useSelector } from '@xstate/react'; -import { i18n } from '@kbn/i18n'; -import { useEuiTheme } from '@elastic/eui'; -import { type DataView, DataViewField } from '@kbn/data-views-plugin/common'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { DEFAULT_LOGS_DATA_VIEW } from '../../common/constants'; -import { useCreateDataView } from './use_create_dataview'; -import { useRedirectLink } from './use_redirect_link'; -import { useDatasetQualityFlyout } from './use_dataset_quality_flyout'; -import { useKibanaContextForPlugin } from '../utils'; -import { useDatasetDetailsTelemetry } from './use_telemetry'; -import { getLensAttributes } from '../components/dataset_quality_details/overview/document_trends/degraded_docs/lens_attributes'; - -const exploreDataInLogsExplorerText = i18n.translate( - 'xpack.datasetQuality.flyoutChartExploreDataInLogsExplorerText', - { - defaultMessage: 'Explore data in Logs Explorer', - } -); - -const exploreDataInDiscoverText = i18n.translate( - 'xpack.datasetQuality.flyoutChartExploreDataInDiscoverText', - { - defaultMessage: 'Explore data in Discover', - } -); - -const openInLensText = i18n.translate('xpack.datasetQuality.flyoutChartOpenInLensText', { - defaultMessage: 'Open in Lens', -}); - -const ACTION_EXPLORE_IN_LOGS_EXPLORER = 'ACTION_EXPLORE_IN_LOGS_EXPLORER'; -const ACTION_OPEN_IN_LENS = 'ACTION_OPEN_IN_LENS'; - -interface DegradedDocsChartDeps { - dataStream?: string; - breakdownField?: string; -} - -export const useDegradedDocsChart = ({ dataStream }: DegradedDocsChartDeps) => { - const { euiTheme } = useEuiTheme(); - const { - services: { lens }, - } = useKibanaContextForPlugin(); - const { service } = useDatasetQualityContext(); - - const { - trackDatasetDetailsBreakdownFieldChanged, - trackDetailsNavigated, - navigationTargets, - navigationSources, - } = useDatasetDetailsTelemetry(); - - const { dataStreamStat, timeRange, breakdownField } = useDatasetQualityFlyout(); - - const isBreakdownFieldEcs = useSelector( - service, - (state) => state.context.flyout.isBreakdownFieldEcs - ); - - const isBreakdownFieldEcsAsserted = useSelector(service, (state) => { - return ( - state.matches('flyout.initializing.assertBreakdownFieldIsEcs.done') && - state.history?.matches('flyout.initializing.assertBreakdownFieldIsEcs.fetching') && - isBreakdownFieldEcs !== null - ); - }); - - const [isChartLoading, setIsChartLoading] = useState(undefined); - const [attributes, setAttributes] = useState | undefined>( - undefined - ); - - const { dataView } = useCreateDataView({ - indexPatternString: getDataViewIndexPattern(dataStream), - }); - - const breakdownDataViewField = useMemo( - () => getDataViewField(dataView, breakdownField), - [breakdownField, dataView] - ); - - const handleChartLoading = (isLoading: boolean) => { - setIsChartLoading(isLoading); - }; - - const handleBreakdownFieldChange = useCallback( - (field: DataViewField | undefined) => { - service.send({ - type: 'BREAKDOWN_FIELD_CHANGE', - breakdownField: field?.name ?? null, - }); - }, - [service] - ); - - useEffect(() => { - if (isBreakdownFieldEcsAsserted) trackDatasetDetailsBreakdownFieldChanged(); - }, [trackDatasetDetailsBreakdownFieldChanged, isBreakdownFieldEcsAsserted]); - - useEffect(() => { - const dataStreamName = dataStream ?? DEFAULT_LOGS_DATA_VIEW; - - const lensAttributes = getLensAttributes({ - color: euiTheme.colors.danger, - dataStream: dataStreamName, - datasetTitle: dataStreamStat?.title ?? dataStreamName, - breakdownFieldName: breakdownDataViewField?.name, - }); - setAttributes(lensAttributes); - }, [ - breakdownDataViewField?.name, - euiTheme.colors.danger, - setAttributes, - dataStream, - dataStreamStat?.title, - ]); - - const openInLensCallback = useCallback(() => { - if (attributes) { - trackDetailsNavigated(navigationTargets.Lens, navigationSources.Chart); - lens.navigateToPrefilledEditor({ - id: '', - timeRange, - attributes, - }); - } - }, [attributes, trackDetailsNavigated, navigationTargets, navigationSources, lens, timeRange]); - - const getOpenInLensAction = useMemo(() => { - return { - id: ACTION_OPEN_IN_LENS, - type: 'link', - order: 17, - getDisplayName(): string { - return openInLensText; - }, - getIconType(): string { - return 'visArea'; - }, - async isCompatible(): Promise { - return true; - }, - async execute(): Promise { - return openInLensCallback(); - }, - }; - }, [openInLensCallback]); - - const redirectLinkProps = useRedirectLink({ - dataStreamStat: dataStreamStat!, - query: { language: 'kuery', query: '_ignored:*' }, - timeRangeConfig: timeRange, - breakdownField: breakdownDataViewField?.name, - telemetry: { - page: 'details', - navigationSource: navigationSources.Chart, - }, - }); - - const getOpenInLogsExplorerAction = useMemo(() => { - return { - id: ACTION_EXPLORE_IN_LOGS_EXPLORER, - type: 'link', - getDisplayName(): string { - return redirectLinkProps?.isLogsExplorerAvailable - ? exploreDataInLogsExplorerText - : exploreDataInDiscoverText; - }, - getHref: async () => { - return redirectLinkProps.linkProps.href; - }, - getIconType(): string | undefined { - return 'visTable'; - }, - async isCompatible(): Promise { - return true; - }, - async execute(): Promise { - return redirectLinkProps.navigate(); - }, - order: 18, - }; - }, [redirectLinkProps]); - - const extraActions: Action[] = [getOpenInLensAction, getOpenInLogsExplorerAction]; - - return { - attributes, - dataView, - breakdown: { - dataViewField: breakdownDataViewField, - fieldSupportsBreakdown: breakdownDataViewField - ? fieldSupportsBreakdown(breakdownDataViewField) - : true, - onChange: handleBreakdownFieldChange, - }, - extraActions, - isChartLoading, - onChartLoading: handleChartLoading, - setAttributes, - setIsChartLoading, - }; -}; - -function getDataViewIndexPattern(dataStream: string | undefined) { - return dataStream ?? DEFAULT_LOGS_DATA_VIEW; -} - -function getDataViewField(dataView: DataView | undefined, fieldName: string | undefined) { - return fieldName && dataView - ? dataView.fields.find((field) => field.name === fieldName) - : undefined; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx deleted file mode 100644 index b0f47716100b4..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx +++ /dev/null @@ -1,104 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getRouterLinkProps } from '@kbn/router-utils'; -import { useMemo, useCallback } from 'react'; -import useToggle from 'react-use/lib/useToggle'; -import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants'; -import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics'; -import { useKibanaContextForPlugin } from '../utils'; -import { Dashboard } from '../../common/api_types'; -import { useDatasetDetailsTelemetry } from './use_telemetry'; - -export const useFlyoutIntegrationActions = () => { - const { - services: { - application: { navigateToUrl }, - http: { basePath }, - share, - }, - } = useKibanaContextForPlugin(); - const { wrapLinkPropsForTelemetry, navigationSources, navigationTargets } = - useDatasetDetailsTelemetry(); - - const [isOpen, toggleIsOpen] = useToggle(false); - - const dashboardLocator = useMemo( - () => share.url.locators.get(DASHBOARD_APP_LOCATOR), - [share.url.locators] - ); - const indexManagementLocator = useMemo( - () => share.url.locators.get(MANAGEMENT_APP_LOCATOR), - [share.url.locators] - ); - - const handleCloseMenu = useCallback(() => { - toggleIsOpen(); - }, [toggleIsOpen]); - const handleToggleMenu = useCallback(() => { - toggleIsOpen(); - }, [toggleIsOpen]); - - const getIntegrationOverviewLinkProps = useCallback( - (name: string, version: string) => { - const href = basePath.prepend(`/app/integrations/detail/${name}-${version}/overview`); - return wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href, - onClick: () => { - return navigateToUrl(href); - }, - }), - navigationTargets.Integration, - navigationSources.ActionMenu - ); - }, - [basePath, navigateToUrl, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] - ); - const getIndexManagementLinkProps = useCallback( - (params: { sectionId: string; appId: string }) => - wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href: indexManagementLocator?.getRedirectUrl(params), - onClick: () => { - return indexManagementLocator?.navigate(params); - }, - }), - navigationTargets.IndexTemplate, - navigationSources.ActionMenu - ), - [ - indexManagementLocator, - navigationSources.ActionMenu, - navigationTargets.IndexTemplate, - wrapLinkPropsForTelemetry, - ] - ); - const getDashboardLinkProps = useCallback( - (dashboard: Dashboard) => - wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), - onClick: () => { - return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); - }, - }), - navigationTargets.Dashboard, - navigationSources.ActionMenu - ), - [dashboardLocator, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] - ); - - return { - isOpen, - handleCloseMenu, - handleToggleMenu, - getIntegrationOverviewLinkProps, - getIndexManagementLinkProps, - getDashboardLinkProps, - }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts index 0fce743875a60..165ac2a651809 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts @@ -12,6 +12,7 @@ import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants'; import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics'; import { useKibanaContextForPlugin } from '../utils'; import { Dashboard } from '../../common/api_types'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; export const useIntegrationActions = () => { const { @@ -21,6 +22,8 @@ export const useIntegrationActions = () => { share, }, } = useKibanaContextForPlugin(); + const { wrapLinkPropsForTelemetry, navigationSources, navigationTargets } = + useDatasetDetailsTelemetry(); const [isOpen, toggleIsOpen] = useToggle(false); @@ -43,34 +46,51 @@ export const useIntegrationActions = () => { const getIntegrationOverviewLinkProps = useCallback( (name: string, version: string) => { const href = basePath.prepend(`/app/integrations/detail/${name}-${version}/overview`); - return getRouterLinkProps({ - href, - onClick: () => { - return navigateToUrl(href); - }, - }); + return wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href, + onClick: () => { + return navigateToUrl(href); + }, + }), + navigationTargets.Integration, + navigationSources.ActionMenu + ); }, - [basePath, navigateToUrl] + [basePath, navigateToUrl, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] ); const getIndexManagementLinkProps = useCallback( (params: { sectionId: string; appId: string }) => - getRouterLinkProps({ - href: indexManagementLocator?.getRedirectUrl(params), - onClick: () => { - return indexManagementLocator?.navigate(params); - }, - }), - [indexManagementLocator] + wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href: indexManagementLocator?.getRedirectUrl(params), + onClick: () => { + return indexManagementLocator?.navigate(params); + }, + }), + navigationTargets.IndexTemplate, + navigationSources.ActionMenu + ), + [ + indexManagementLocator, + navigationSources.ActionMenu, + navigationTargets.IndexTemplate, + wrapLinkPropsForTelemetry, + ] ); const getDashboardLinkProps = useCallback( (dashboard: Dashboard) => - getRouterLinkProps({ - href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), - onClick: () => { - return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); - }, - }), - [dashboardLocator] + wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), + onClick: () => { + return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); + }, + }), + navigationTargets.Dashboard, + navigationSources.ActionMenu + ), + [dashboardLocator, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] ); return { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts index e4fbf0771ee1f..d83ad8299e263 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts @@ -18,20 +18,20 @@ import { LocatorPublic } from '@kbn/share-plugin/common'; import { LocatorClient } from '@kbn/shared-ux-prompt-no-data-views-types'; import { useKibanaContextForPlugin } from '../utils'; import { BasicDataStream, TimeRangeConfig } from '../../common/types'; -import { useRedirectLinkTelemetry } from './use_telemetry'; +import { SendTelemetryFn } from './use_redirect_link_telemetry'; export const useRedirectLink = ({ dataStreamStat, query, timeRangeConfig, breakdownField, - telemetry, + sendTelemetry, }: { dataStreamStat: T; query?: Query | AggregateQuery; timeRangeConfig: TimeRangeConfig; breakdownField?: string; - telemetry?: Parameters[0]['telemetry']; + sendTelemetry: SendTelemetryFn; }) => { const { services: { share }, @@ -42,13 +42,6 @@ export const useRedirectLink = ({ const logsExplorerLocator = share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); - const { sendTelemetry } = useRedirectLinkTelemetry({ - rawName: dataStreamStat.rawName, - isLogsExplorer: !!logsExplorerLocator, - telemetry, - query, - }); - return useMemo<{ linkProps: RouterLinkProps; navigate: () => void; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts new file mode 100644 index 0000000000000..a70de0bd20295 --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts @@ -0,0 +1,75 @@ +/* + * 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 { useCallback } from 'react'; +import { AggregateQuery, Query } from '@kbn/es-query'; +import { + SINGLE_DATASET_LOCATOR_ID, + SingleDatasetLocatorParams, +} from '@kbn/deeplinks-observability'; +import { NavigationSource } from '../services/telemetry'; +import { useDatasetTelemetry } from './use_dataset_telemetry'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; +import { useKibanaContextForPlugin } from '../utils'; + +export type SendTelemetryFn = + | ReturnType['sendTelemetry'] + | ReturnType['sendTelemetry']; + +export const useDatasetRedirectLinkTelemetry = ({ + rawName, + query, +}: { + rawName: string; + query?: Query | AggregateQuery; +}) => { + const { trackDatasetNavigated } = useDatasetTelemetry(); + + const sendTelemetry = useCallback(() => { + const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; + + trackDatasetNavigated(rawName, isIgnoredFilter); + }, [query, rawName, trackDatasetNavigated]); + + return { + sendTelemetry, + }; +}; + +export const useDatasetDetailsRedirectLinkTelemetry = ({ + query, + navigationSource, +}: { + navigationSource: NavigationSource; + query?: Query | AggregateQuery; +}) => { + const { + services: { share }, + } = useKibanaContextForPlugin(); + const logsExplorerLocator = + share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); + const isLogsExplorer = !!logsExplorerLocator; + const { trackDetailsNavigated, navigationTargets } = useDatasetDetailsTelemetry(); + + const sendTelemetry = useCallback(() => { + const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; + const target = isLogsExplorer ? navigationTargets.LogsExplorer : navigationTargets.Discover; + + trackDetailsNavigated(target, navigationSource, isIgnoredFilter); + }, [ + query, + isLogsExplorer, + navigationTargets.LogsExplorer, + navigationTargets.Discover, + trackDetailsNavigated, + navigationSource, + ]); + + return { + sendTelemetry, + }; +}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts similarity index 100% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.tsx rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx deleted file mode 100644 index c473495c0a661..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx +++ /dev/null @@ -1,382 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { useCallback, useEffect, useMemo } from 'react'; -import { useSelector } from '@xstate/react'; -import { getDateISORange } from '@kbn/timerange'; -import { AggregateQuery, Query } from '@kbn/es-query'; - -import { MASKED_FIELD_PLACEHOLDER, UNKOWN_FIELD_PLACEHOLDER } from '../../common/constants'; -import { DataStreamStat } from '../../common/data_streams_stats'; -import { DataStreamDetails } from '../../common/api_types'; -import { mapPercentageToQuality } from '../../common/utils'; -import { - NavigationTarget, - NavigationSource, - DatasetDetailsEbtProps, - DatasetNavigatedEbtProps, - DatasetEbtProps, -} from '../services/telemetry'; -import { FlyoutDataset } from '../state_machines/dataset_quality_controller'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { useDatasetQualityFilters } from './use_dataset_quality_filters'; -import { TimeRangeConfig } from '../../common/types'; - -export const useRedirectLinkTelemetry = ({ - rawName, - isLogsExplorer, - telemetry, - query, -}: { - rawName: string; - isLogsExplorer: boolean; - telemetry?: { - page: 'main' | 'details'; - navigationSource: NavigationSource; - }; - query?: Query | AggregateQuery; -}) => { - const { trackDatasetNavigated } = useDatasetTelemetry(); - const { trackDetailsNavigated, navigationTargets } = useDatasetDetailsTelemetry(); - - const sendTelemetry = useCallback(() => { - if (telemetry) { - const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; - if (telemetry.page === 'main') { - trackDatasetNavigated(rawName, isIgnoredFilter); - } else { - trackDetailsNavigated( - isLogsExplorer ? navigationTargets.LogsExplorer : navigationTargets.Discover, - telemetry.navigationSource, - isIgnoredFilter - ); - } - } - }, [ - isLogsExplorer, - trackDetailsNavigated, - navigationTargets, - query, - rawName, - telemetry, - trackDatasetNavigated, - ]); - - const wrapLinkPropsForTelemetry = useCallback( - (props: RouterLinkProps) => { - return { - ...props, - onClick: (event: Parameters[0]) => { - sendTelemetry(); - if (props.onClick) { - props.onClick(event); - } - }, - }; - }, - [sendTelemetry] - ); - - return { - wrapLinkPropsForTelemetry, - sendTelemetry, - }; -}; - -export const useDatasetTelemetry = () => { - const { service, telemetryClient } = useDatasetQualityContext(); - - // eslint-disable-next-line react-hooks/exhaustive-deps - const datasets = useSelector(service, (state) => state.context.datasets) ?? {}; - const nonAggregatableDatasets = useSelector( - service, - (state) => state.context.nonAggregatableDatasets - ); - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - const sort = useSelector(service, (state) => state.context.table.sort); - const appliedFilters = useDatasetQualityFilters(); - - const trackDatasetNavigated = useCallback<(rawName: string, isIgnoredFilter: boolean) => void>( - (rawName: string, isIgnoredFilter: boolean) => { - const foundDataset = datasets.find((dataset) => dataset.rawName === rawName); - if (foundDataset) { - const ebtProps = getDatasetEbtProps( - foundDataset, - sort, - appliedFilters, - nonAggregatableDatasets, - isIgnoredFilter, - canUserViewIntegrations - ); - telemetryClient.trackDatasetNavigated(ebtProps); - } else { - throw new Error( - `Cannot report dataset navigation telemetry for unknown dataset ${rawName}` - ); - } - }, - [ - sort, - appliedFilters, - canUserViewIntegrations, - datasets, - nonAggregatableDatasets, - telemetryClient, - ] - ); - - return { trackDatasetNavigated }; -}; - -export const useDatasetDetailsTelemetry = () => { - const { service, telemetryClient } = useDatasetQualityContext(); - - const { - dataset: dataStreamStat, - datasetDetails: dataStreamDetails, - insightsTimeRange, - breakdownField, - isNonAggregatable, - isBreakdownFieldEcs, - } = useSelector(service, (state) => state.context.flyout) ?? {}; - - const loadingState = useSelector(service, (state) => ({ - dataStreamDetailsLoading: - state.matches('flyout.initializing.dataStreamDetails.fetching') || - state.matches('flyout.initializing.assertBreakdownFieldIsEcs.fetching'), - })); - - const canUserAccessDashboards = useSelector( - service, - (state) => !state.matches('flyout.initializing.integrationDashboards.unauthorized') - ); - - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - - const ebtProps = useMemo(() => { - if ( - dataStreamDetails && - insightsTimeRange && - dataStreamStat && - !loadingState.dataStreamDetailsLoading - ) { - return getDatasetDetailsEbtProps( - insightsTimeRange, - dataStreamStat, - dataStreamDetails, - isNonAggregatable ?? false, - canUserViewIntegrations, - canUserAccessDashboards, - isBreakdownFieldEcs, - breakdownField - ); - } - - return undefined; - }, [ - insightsTimeRange, - dataStreamStat, - dataStreamDetails, - loadingState.dataStreamDetailsLoading, - isNonAggregatable, - canUserViewIntegrations, - canUserAccessDashboards, - isBreakdownFieldEcs, - breakdownField, - ]); - - const startTracking = useCallback(() => { - telemetryClient.startDatasetDetailsTracking(); - }, [telemetryClient]); - - // Report opening dataset details - useEffect(() => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if (datasetDetailsTrackingState === 'started' && ebtProps) { - telemetryClient.trackDatasetDetailsOpened(ebtProps); - } - }, [ebtProps, telemetryClient]); - - const trackDetailsNavigated = useCallback( - (target: NavigationTarget, source: NavigationSource, isDegraded = false) => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if ( - (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && - ebtProps - ) { - telemetryClient.trackDatasetDetailsNavigated({ - ...ebtProps, - filters: { - is_degraded: isDegraded, - }, - target, - source, - }); - } else { - throw new Error( - 'Cannot report dataset details navigation telemetry without required data and state' - ); - } - }, - [ebtProps, telemetryClient] - ); - - const trackDatasetDetailsBreakdownFieldChanged = useCallback(() => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if ( - (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && - ebtProps - ) { - telemetryClient.trackDatasetDetailsBreakdownFieldChanged({ - ...ebtProps, - breakdown_field: ebtProps.breakdown_field, - }); - } - }, [ebtProps, telemetryClient]); - - const wrapLinkPropsForTelemetry = useCallback( - ( - props: RouterLinkProps, - target: NavigationTarget, - source: NavigationSource, - isDegraded = false - ) => { - return { - ...props, - onClick: (event: Parameters[0]) => { - trackDetailsNavigated(target, source, isDegraded); - if (props.onClick) { - props.onClick(event); - } - }, - }; - }, - [trackDetailsNavigated] - ); - - return { - startTracking, - trackDetailsNavigated, - wrapLinkPropsForTelemetry, - navigationTargets: NavigationTarget, - navigationSources: NavigationSource, - trackDatasetDetailsBreakdownFieldChanged, - }; -}; - -function getDatasetEbtProps( - dataset: DataStreamStat, - sort: { field: string; direction: 'asc' | 'desc' }, - filters: ReturnType, - nonAggregatableDatasets: string[], - isIgnoredFilter: boolean, - canUserViewIntegrations: boolean -): DatasetNavigatedEbtProps { - const { startDate: from, endDate: to } = getDateISORange(filters.timeRange); - const datasetEbtProps: DatasetEbtProps = { - index_name: dataset.rawName, - data_stream: { - dataset: dataset.name, - namespace: dataset.namespace, - type: dataset.type, - }, - data_stream_health: dataset.degradedDocs.quality, - data_stream_aggregatable: nonAggregatableDatasets.some( - (indexName) => indexName === dataset.rawName - ), - from, - to, - degraded_percentage: dataset.degradedDocs.percentage, - integration: dataset.integration?.name, - privileges: { - can_monitor_data_stream: dataset.userPrivileges?.canMonitor ?? true, - can_view_integrations: canUserViewIntegrations, - }, - }; - - const ebtFilters: DatasetNavigatedEbtProps['filters'] = { - is_degraded: isIgnoredFilter, - query_length: filters.selectedQuery?.length ?? 0, - integrations: { - total: filters.integrations.filter((item) => item.name !== 'none').length, - included: filters.integrations.filter((item) => item?.checked === 'on').length, - excluded: filters.integrations.filter((item) => item?.checked === 'off').length, - }, - namespaces: { - total: filters.namespaces.length, - included: filters.namespaces.filter((item) => item?.checked === 'on').length, - excluded: filters.namespaces.filter((item) => item?.checked === 'off').length, - }, - qualities: { - total: filters.qualities.length, - included: filters.qualities.filter((item) => item?.checked === 'on').length, - excluded: filters.qualities.filter((item) => item?.checked === 'off').length, - }, - }; - - return { - ...datasetEbtProps, - sort, - filters: ebtFilters, - }; -} - -function getDatasetDetailsEbtProps( - insightsTimeRange: TimeRangeConfig, - flyoutDataset: FlyoutDataset, - details: DataStreamDetails, - isNonAggregatable: boolean, - canUserViewIntegrations: boolean, - canUserAccessDashboards: boolean, - isBreakdownFieldEcs: boolean | null, - breakdownField?: string -): DatasetDetailsEbtProps { - const indexName = flyoutDataset.rawName; - const dataStream = { - dataset: flyoutDataset.name, - namespace: flyoutDataset.namespace, - type: flyoutDataset.type, - }; - const degradedDocs = details?.degradedDocsCount ?? 0; - const totalDocs = details?.docsCount ?? 0; - const degradedPercentage = - totalDocs > 0 ? Number(((degradedDocs / totalDocs) * 100).toFixed(2)) : 0; - const health = mapPercentageToQuality(degradedPercentage); - const { startDate: from, endDate: to } = getDateISORange(insightsTimeRange); - - return { - index_name: indexName, - data_stream: dataStream, - privileges: { - can_monitor_data_stream: true, - can_view_integrations: canUserViewIntegrations, - can_view_dashboards: canUserAccessDashboards, - }, - data_stream_aggregatable: !isNonAggregatable, - data_stream_health: health, - from, - to, - degraded_percentage: degradedPercentage, - integration: flyoutDataset.integration?.name, - breakdown_field: breakdownField - ? isBreakdownFieldEcs === null - ? UNKOWN_FIELD_PLACEHOLDER - : getMaskedBreakdownField(breakdownField, isBreakdownFieldEcs) - : breakdownField, - }; -} - -function getMaskedBreakdownField(breakdownField: string, isBreakdownFieldEcs: boolean) { - return isBreakdownFieldEcs ? breakdownField : MASKED_FIELD_PLACEHOLDER; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx index 6cb4c12975412..84dbabe1d2540 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx @@ -52,9 +52,7 @@ export class DatasetQualityPlugin const createDatasetQualityController = createDatasetQualityControllerLazyFactory({ core, - plugins, dataStreamStatsClient, - dataStreamDetailsClient, }); const DatasetQualityDetails = createDatasetQualityDetails({ diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts index e4b5e07c8df92..f1a41ffc666cc 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts @@ -34,6 +34,7 @@ export enum NavigationSource { Footer = 'footer', Summary = 'summary', Chart = 'chart', + Trend = 'trend', Table = 'table', ActionMenu = 'action_menu', } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts index 62ec47632c242..87a6a398df8f0 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts @@ -7,8 +7,6 @@ import { DEFAULT_DATASET_TYPE, - DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - DEFAULT_DEGRADED_FIELD_SORT_FIELD, DEFAULT_SORT_DIRECTION, DEFAULT_SORT_FIELD, } from '../../../../common/constants'; @@ -47,19 +45,6 @@ export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { namespaces: [], qualities: [], }, - flyout: { - degradedFields: { - table: { - page: 0, - rowsPerPage: 10, - sort: { - field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, - }, - }, - isBreakdownFieldEcs: null, - }, datasets: [], isSizeStatsAvailable: true, nonAggregatableDatasets: [], diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts index f10ea32da3af6..a21cc85aac449 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts @@ -17,15 +17,6 @@ export const fetchDatasetStatsFailedNotifier = (toasts: IToasts, error: Error) = }); }; -export const fetchDatasetDetailsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.fetchDatasetDetailsFailed', { - defaultMessage: "We couldn't get your data set details.", - }), - text: error.message, - }); -}; - export const fetchDegradedStatsFailedNotifier = (toasts: IToasts, error: Error) => { toasts.addDanger({ title: i18n.translate('xpack.datasetQuality.fetchDegradedStatsFailed', { @@ -35,15 +26,6 @@ export const fetchDegradedStatsFailedNotifier = (toasts: IToasts, error: Error) }); }; -export const fetchNonAggregatableDatasetsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.fetchNonAggregatableDatasetsFailed', { - defaultMessage: "We couldn't get non aggregatable datasets information.", - }), - text: error.message, - }); -}; - export const fetchIntegrationsFailedNotifier = (toasts: IToasts, error: Error) => { toasts.addDanger({ title: i18n.translate('xpack.datasetQuality.fetchIntegrationsFailed', { @@ -52,19 +34,3 @@ export const fetchIntegrationsFailedNotifier = (toasts: IToasts, error: Error) = text: error.message, }); }; - -export const noDatasetSelected = i18n.translate( - 'xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected', - { - defaultMessage: 'No data set have been selected', - } -); - -export const assertBreakdownFieldEcsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.assertBreakdownFieldEcsFailed', { - defaultMessage: "We couldn't retrieve breakdown field metadata.", - }), - text: error.message, - }); -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts index fb6c03fae153a..7ce3c5b5d8f60 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts @@ -8,36 +8,22 @@ import { IToasts } from '@kbn/core/public'; import { getDateISORange } from '@kbn/timerange'; import { assign, createMachine, DoneInvokeEvent, InterpreterFrom } from 'xstate'; -import { DatasetQualityStartDeps } from '../../../types'; -import { - Dashboard, - DataStreamStat, - DegradedFieldResponse, - NonAggregatableDatasets, -} from '../../../../common/api_types'; +import { DataStreamStat, NonAggregatableDatasets } from '../../../../common/api_types'; import { Integration } from '../../../../common/data_streams_stats/integration'; -import { IDataStreamDetailsClient } from '../../../services/data_stream_details'; import { - DataStreamSettings, - DataStreamDetails, GetDataStreamsStatsQuery, GetIntegrationsParams, GetNonAggregatableDataStreamsParams, DataStreamStatServiceResponse, } from '../../../../common/data_streams_stats'; import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; -import { DataStreamType } from '../../../../common/types'; -import { dataStreamPartsToIndexName } from '../../../../common/utils'; import { IDataStreamsStatsClient } from '../../../services/data_streams_stats'; import { generateDatasets } from '../../../utils'; import { DEFAULT_CONTEXT } from './defaults'; import { - fetchDatasetDetailsFailedNotifier, fetchDatasetStatsFailedNotifier, fetchDegradedStatsFailedNotifier, fetchIntegrationsFailedNotifier, - noDatasetSelected, - assertBreakdownFieldEcsFailedNotifier, } from './notifications'; import { fetchNonAggregatableDatasetsFailedNotifier } from '../../common/notifications'; import { @@ -45,13 +31,7 @@ import { DatasetQualityControllerEvent, DatasetQualityControllerTypeState, DefaultDatasetQualityControllerState, - FlyoutDataset, } from './types'; -import { - fetchDataStreamSettingsFailedNotifier, - fetchIntegrationDashboardsFailedNotifier, - fetchDataStreamIntegrationFailedNotifier, -} from '../../dataset_quality_details_controller/notifications'; export const createPureDatasetQualityControllerStateMachine = ( initialContext: DatasetQualityControllerContext @@ -227,231 +207,6 @@ export const createPureDatasetQualityControllerStateMachine = ( }, }, }, - flyout: { - initial: 'closed', - states: { - initializing: { - type: 'parallel', - states: { - nonAggregatableDataset: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDatasetIsNonAggregatable', - onDone: { - target: 'done', - actions: ['storeDatasetIsNonAggregatable'], - }, - onError: { - target: 'done', - actions: ['notifyFetchNonAggregatableDatasetsFailed'], - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - SELECT_DATASET: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - }, - dataStreamSettings: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamSettings', - onDone: { - target: 'initializeIntegrations', - actions: ['storeDataStreamSettings'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDataStreamSettingsFailed'], - }, - }, - }, - initializeIntegrations: { - type: 'parallel', - states: { - integrationDetails: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamIntegration', - onDone: { - target: 'done', - actions: ['storeDataStreamIntegration'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDatasetIntegrationsFailed'], - }, - }, - }, - done: { - type: 'final', - }, - }, - }, - integrationDashboards: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadIntegrationDashboards', - onDone: { - target: 'done', - actions: ['storeIntegrationDashboards'], - }, - onError: [ - { - target: 'unauthorized', - cond: 'checkIfActionForbidden', - }, - { - target: 'done', - actions: ['notifyFetchIntegrationDashboardsFailed'], - }, - ], - }, - }, - done: { - type: 'final', - }, - unauthorized: { - type: 'final', - }, - }, - }, - }, - }, - done: { - type: 'final', - }, - }, - }, - dataStreamDetails: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamDetails', - onDone: { - target: 'done', - actions: ['storeDatasetDetails'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDatasetDetailsFailed'], - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - BREAKDOWN_FIELD_CHANGE: { - target: - '#DatasetQualityController.flyout.initializing.assertBreakdownFieldIsEcs.fetching', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - }, - dataStreamDegradedFields: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDegradedFieldsPerDataStream', - onDone: { - target: 'done', - actions: ['storeDegradedFields'], - }, - onError: { - target: 'done', - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['resetDegradedFieldPage'], - }, - UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA: { - target: 'done', - actions: ['storeDegradedFieldTableOptions'], - }, - }, - }, - }, - }, - assertBreakdownFieldIsEcs: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'assertBreakdownFieldIsEcs', - onDone: { - target: 'done', - actions: ['storeBreakdownFieldIsEcs'], - }, - onError: { - target: 'done', - actions: ['notifyAssertBreakdownFieldEcsFailed'], - }, - }, - }, - done: {}, - }, - }, - }, - onDone: { - target: '#DatasetQualityController.flyout.loaded', - }, - }, - loaded: { - on: { - CLOSE_FLYOUT: { - target: 'closed', - actions: ['resetFlyoutOptions'], - }, - }, - }, - closed: { - on: { - OPEN_FLYOUT: { - target: '#DatasetQualityController.flyout.initializing', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - on: { - SELECT_NEW_DATASET: { - target: '#DatasetQualityController.flyout.initializing', - actions: ['storeFlyoutOptions'], - }, - CLOSE_FLYOUT: { - target: '#DatasetQualityController.flyout.closed', - actions: ['resetFlyoutOptions'], - }, - }, - }, }, }, { @@ -463,38 +218,12 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), - storeDegradedFieldTableOptions: assign((context, event) => { - return 'degraded_field_criteria' in event - ? { - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - table: event.degraded_field_criteria, - }, - }, - } - : {}; - }), resetPage: assign((context, _event) => ({ table: { ...context.table, page: 0, }, })), - resetDegradedFieldPage: assign((context, _event) => ({ - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - table: { - ...context.flyout.degradedFields.table, - page: 0, - rowsPerPage: 10, - }, - }, - }, - })), storeInactiveDatasetsVisibility: assign((context, _event) => { return { filters: { @@ -561,37 +290,6 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), - storeFlyoutOptions: assign((context, event) => { - const insightsTimeRange = - 'timeRange' in event - ? event.timeRange - : context.flyout?.insightsTimeRange ?? context.filters?.timeRange; - const dataset = - 'dataset' in event ? (event.dataset as FlyoutDataset) : context.flyout?.dataset; - const breakdownField = - 'breakdownField' in event - ? event.breakdownField ?? undefined - : context.flyout?.breakdownField; - - return { - flyout: { - ...context.flyout, - dataset, - insightsTimeRange, - breakdownField, - }, - }; - }), - storeBreakdownFieldIsEcs: assign((context, event: DoneInvokeEvent) => { - return { - flyout: { - ...context.flyout, - isBreakdownFieldEcs: - 'data' in event && typeof event.data === 'boolean' ? event.data : null, - }, - }; - }), - resetFlyoutOptions: assign((_context, _event) => ({ flyout: DEFAULT_CONTEXT.flyout })), storeDataStreamStats: assign( (_context, event: DoneInvokeEvent) => { if ('data' in event && 'dataStreamsStats' in event.data) { @@ -618,19 +316,6 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), - storeDegradedFields: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - data: event.data.degradedFields, - }, - }, - } - : {}; - }), storeNonAggregatableDatasets: assign( ( _context: DefaultDatasetQualityControllerState, @@ -643,41 +328,6 @@ export const createPureDatasetQualityControllerStateMachine = ( : {}; } ), - storeDataStreamSettings: assign((context, event) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - dataStreamSettings: (event.data ?? {}) as DataStreamSettings, - }, - } - : {}; - }), - storeDatasetDetails: assign((context, event) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - datasetDetails: event.data as DataStreamDetails, - }, - } - : {}; - }), - storeDatasetIsNonAggregatable: assign( - ( - context: DefaultDatasetQualityControllerState, - event: DoneInvokeEvent - ) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - isNonAggregatable: !event.data.aggregatable, - }, - } - : {}; - } - ), storeIntegrations: assign((_context, event) => { return 'data' in event ? { @@ -690,32 +340,6 @@ export const createPureDatasetQualityControllerStateMachine = ( integrations: [], }; }), - storeDataStreamIntegration: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - integration: { - ...context.flyout.integration, - integrationDetails: event.data, - }, - }, - } - : {}; - }), - storeIntegrationDashboards: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - integration: { - ...context.flyout.integration, - dashboards: event.data, - }, - }, - } - : {}; - }), storeDatasets: assign((context, _event) => { return context.integrations && (context.dataStreamStats || context.degradedDocStats) ? { @@ -743,18 +367,14 @@ export const createPureDatasetQualityControllerStateMachine = ( export interface DatasetQualityControllerStateMachineDependencies { initialContext?: DatasetQualityControllerContext; - plugins: DatasetQualityStartDeps; toasts: IToasts; dataStreamStatsClient: IDataStreamsStatsClient; - dataStreamDetailsClient: IDataStreamDetailsClient; } export const createDatasetQualityControllerStateMachine = ({ initialContext = DEFAULT_CONTEXT, - plugins, toasts, dataStreamStatsClient, - dataStreamDetailsClient, }: DatasetQualityControllerStateMachineDependencies) => createPureDatasetQualityControllerStateMachine(initialContext).withConfig({ actions: { @@ -764,20 +384,8 @@ export const createDatasetQualityControllerStateMachine = ({ fetchDegradedStatsFailedNotifier(toasts, event.data), notifyFetchNonAggregatableDatasetsFailed: (_context, event: DoneInvokeEvent) => fetchNonAggregatableDatasetsFailedNotifier(toasts, event.data), - notifyFetchDataStreamSettingsFailed: (_context, event: DoneInvokeEvent) => - fetchDataStreamSettingsFailedNotifier(toasts, event.data), - notifyFetchDatasetDetailsFailed: (_context, event: DoneInvokeEvent) => - fetchDatasetDetailsFailedNotifier(toasts, event.data), - notifyFetchIntegrationDashboardsFailed: (_context, event: DoneInvokeEvent) => - fetchIntegrationDashboardsFailedNotifier(toasts, event.data), notifyFetchIntegrationsFailed: (_context, event: DoneInvokeEvent) => fetchIntegrationsFailedNotifier(toasts, event.data), - notifyFetchDatasetIntegrationsFailed: (context, event: DoneInvokeEvent) => { - const integrationName = context.flyout.dataStreamSettings?.integration; - return fetchDataStreamIntegrationFailedNotifier(toasts, event.data, integrationName); - }, - notifyAssertBreakdownFieldEcsFailed: (_context, event: DoneInvokeEvent) => - assertBreakdownFieldEcsFailedNotifier(toasts, event.data), }, services: { loadDataStreamStats: (context) => @@ -795,27 +403,6 @@ export const createDatasetQualityControllerStateMachine = ({ end, }); }, - - loadDegradedFieldsPerDataStream: (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - return Promise.resolve({}); - } - - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - const { type, name: dataset, namespace } = context.flyout.dataset; - - return dataStreamDetailsClient.getDataStreamDegradedFields({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - start, - end, - }); - }, loadIntegrations: (context) => { return dataStreamStatsClient.getIntegrations({ type: context.type as GetIntegrationsParams['query']['type'], @@ -830,108 +417,6 @@ export const createDatasetQualityControllerStateMachine = ({ end, }); }, - loadDataStreamSettings: (context) => { - if (!context.flyout.dataset) { - fetchDataStreamSettingsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - - return dataStreamDetailsClient.getDataStreamSettings({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - }); - }, - loadDataStreamIntegration: (context) => { - if (context.flyout.dataStreamSettings?.integration && context.flyout.dataset) { - const { type } = context.flyout.dataset; - return dataStreamDetailsClient.getDataStreamIntegration({ - type: type as DataStreamType, - integrationName: context.flyout.dataStreamSettings.integration, - }); - } - return Promise.resolve(); - }, - loadDataStreamDetails: (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - fetchDatasetDetailsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - - return dataStreamDetailsClient.getDataStreamDetails({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - start, - end, - }); - }, - loadIntegrationDashboards: (context) => { - if (context.flyout.dataStreamSettings?.integration) { - return dataStreamDetailsClient.getIntegrationDashboards({ - integration: context.flyout.dataStreamSettings.integration, - }); - } - - return Promise.resolve(); - }, - loadDatasetIsNonAggregatable: async (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - fetchDatasetDetailsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - - return dataStreamStatsClient.getNonAggregatableDatasets({ - type: context.type as GetNonAggregatableDataStreamsParams['type'], - start, - end, - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - }); - }, - assertBreakdownFieldIsEcs: async (context) => { - if (context.flyout.breakdownField) { - const allowedFieldSources = ['ecs', 'metadata']; - - // This timeout is to avoid a runtime error that randomly happens on breakdown field change - // TypeError: Cannot read properties of undefined (reading 'timeFieldName') - await new Promise((res) => setTimeout(res, 300)); - - const client = await plugins.fieldsMetadata.getClient(); - const { fields } = await client.find({ - attributes: ['source'], - fieldNames: [context.flyout.breakdownField], - }); - - const breakdownFieldSource = fields[context.flyout.breakdownField]?.source; - - return !!(breakdownFieldSource && allowedFieldSources.includes(breakdownFieldSource)); - } - - return null; - }, }, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts index d6bfaaad216b9..a03bddcc9e93e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts @@ -7,35 +7,18 @@ import { DoneInvokeEvent } from 'xstate'; import { QualityIndicators, TableCriteria, TimeRangeConfig } from '../../../../common/types'; -import { - Dashboard, - DatasetUserPrivileges, - NonAggregatableDatasets, -} from '../../../../common/api_types'; +import { DatasetUserPrivileges, NonAggregatableDatasets } from '../../../../common/api_types'; import { Integration } from '../../../../common/data_streams_stats/integration'; -import { DatasetTableSortField, DegradedFieldSortField } from '../../../hooks'; +import { DatasetTableSortField } from '../../../hooks'; import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; import { DataStreamDegradedDocsStatServiceResponse, - DataStreamSettings, DataStreamDetails, DataStreamStatServiceResponse, DataStreamStat, DataStreamStatType, - DegradedField, - DegradedFieldResponse, } from '../../../../common/data_streams_stats'; -export type FlyoutDataset = Omit< - DataStreamStat, - 'type' | 'size' | 'sizeBytes' | 'lastActivity' | 'degradedDocs' -> & { type: string }; - -export interface DegradedFields { - table: TableCriteria; - data?: DegradedField[]; -} - interface FiltersCriteria { inactive: boolean; fullNames: boolean; @@ -46,29 +29,10 @@ interface FiltersCriteria { query?: string; } -export interface DataStreamIntegrations { - integrationDetails?: Integration; - dashboards?: Dashboard[]; -} - export interface WithTableOptions { table: TableCriteria; } -export interface WithFlyoutOptions { - flyout: { - dataset?: FlyoutDataset; - dataStreamSettings?: DataStreamSettings; - datasetDetails?: DataStreamDetails; - insightsTimeRange?: TimeRangeConfig; - breakdownField?: string; - degradedFields: DegradedFields; - isNonAggregatable?: boolean; - integration?: DataStreamIntegrations; - isBreakdownFieldEcs: boolean | null; - }; -} - export interface WithFilters { filters: FiltersCriteria; } @@ -98,14 +62,12 @@ export interface WithIntegrations { export type DefaultDatasetQualityControllerState = { type: string } & WithTableOptions & WithDataStreamStats & Partial & - WithFlyoutOptions & WithDatasets & WithFilters & WithNonAggregatableDatasets & Partial; -type DefaultDatasetQualityStateContext = DefaultDatasetQualityControllerState & - Partial; +type DefaultDatasetQualityStateContext = DefaultDatasetQualityControllerState; export type DatasetQualityControllerTypeState = | { @@ -131,48 +93,6 @@ export type DatasetQualityControllerTypeState = | { value: 'nonAggregatableDatasets.fetching'; context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.unauthorized'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDetails.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDetails.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDetails.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.assertBreakdownFieldIsEcs.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.assertBreakdownFieldIsEcs.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDegradedFields.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: - | 'flyout.initializing.integrationDashboards.fetching' - | 'flyout.initializing.integrationDashboards.unauthorized'; - context: DefaultDatasetQualityStateContext; }; export type DatasetQualityControllerContext = DatasetQualityControllerTypeState['context']; @@ -182,29 +102,10 @@ export type DatasetQualityControllerEvent = type: 'UPDATE_TABLE_CRITERIA'; dataset_criteria: TableCriteria; } - | { - type: 'UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA'; - degraded_field_criteria: TableCriteria; - } - | { - type: 'OPEN_FLYOUT'; - dataset: FlyoutDataset; - } - | { - type: 'SELECT_NEW_DATASET'; - dataset: FlyoutDataset; - } | { type: 'UPDATE_INSIGHTS_TIME_RANGE'; timeRange: TimeRangeConfig; } - | { - type: 'BREAKDOWN_FIELD_CHANGE'; - breakdownField: string | null; - } - | { - type: 'CLOSE_FLYOUT'; - } | { type: 'TOGGLE_INACTIVE_DATASETS'; } @@ -236,10 +137,7 @@ export type DatasetQualityControllerEvent = } | DoneInvokeEvent | DoneInvokeEvent - | DoneInvokeEvent | DoneInvokeEvent - | DoneInvokeEvent - | DoneInvokeEvent | DoneInvokeEvent | DoneInvokeEvent | DoneInvokeEvent diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 53dcc0869d477..86e3e5702baad 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -14613,7 +14613,6 @@ "xpack.datasetQuality.appTitle": "Qualité de l’ensemble de données", "xpack.datasetQuality.betaBadgeDescription": "Cette fonctionnalité est actuellement en version bêta. Nous aimerions beaucoup savoir si vous avez des commentaires ou si vous rencontrez des bugs. Veuillez ouvrir un dossier d'assistance et/ou consulter notre forum de discussion.", "xpack.datasetQuality.betaBadgeLabel": "Bêta", - "xpack.datasetQuality.collapseLabel": "Réduire", "xpack.datasetQuality.datasetQualityColumnName": "Qualité de l’ensemble de données", "xpack.datasetQuality.datasetQualityColumnTooltip": "La qualité est basée sur le pourcentage de documents dégradés dans un ensemble de données. {visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14624,9 +14623,6 @@ "xpack.datasetQuality.emptyState.noData.title": "Aucun ensemble de données trouvé", "xpack.datasetQuality.emptyState.noPrivileges.message": "Vous ne disposez pas des autorisations requises pour voir les données de logs. Assurez-vous d'avoir les autorisations requises pour voir {datasetPattern}.", "xpack.datasetQuality.emptyState.noPrivileges.title": "Impossible de charger les ensembles de données", - "xpack.datasetQuality.expandLabel": "Développer", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "Nous n'avons pas pu obtenir les détails de votre ensemble de données.", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "Vous n'avez sélectionné aucun ensemble de données", "xpack.datasetQuality.fetchDatasetStatsFailed": "Nous n'avons pas pu obtenir vos ensembles de données.", "xpack.datasetQuality.fetchDegradedStatsFailed": "Nous n'avons pas pu obtenir d'informations sur vos documents dégradés.", "xpack.datasetQuality.fetchIntegrationsFailed": "Nous n'avons pas pu obtenir vos intégrations.", @@ -14634,9 +14630,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "{degradedDocsCount} documents dégradés dans cet ensemble de données.", "xpack.datasetQuality.filterBar.placeholder": "Filtrer les ensembles de données", "xpack.datasetQuality.flyout.degradedDocsTitle": "Documents dégradés", - "xpack.datasetQuality.flyout.degradedField.count": "Nombre de documents", - "xpack.datasetQuality.flyout.degradedField.field": "Champ", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "Dernière occurrence", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "{rolloverLink} manuellement cet ensemble de données pour empêcher des délais à l'avenir.", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset} est incompatible avec l'agrégation _ignored, ce qui peut entraîner des délais lors de la recherche de données. {howToFixIt}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e89e452923f30..0ab34991b457d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14602,7 +14602,6 @@ "xpack.datasetQuality.appTitle": "データセット品質", "xpack.datasetQuality.betaBadgeDescription": "現在、この機能はベータです。バグが発生した場合やフィードバックがある場合は、お問い合わせください。サポート問題をオープンするか、ディスカッションフォーラムをご覧ください。", "xpack.datasetQuality.betaBadgeLabel": "ベータ", - "xpack.datasetQuality.collapseLabel": "縮小", "xpack.datasetQuality.datasetQualityColumnName": "データセット品質", "xpack.datasetQuality.datasetQualityColumnTooltip": "品質は、データセットの劣化したドキュメントの割合に基づきます。{visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14613,9 +14612,6 @@ "xpack.datasetQuality.emptyState.noData.title": "データセットが見つかりません", "xpack.datasetQuality.emptyState.noPrivileges.message": "ログデータを表示するために必要な権限がありません。{datasetPattern}を表示するための十分な権限があることを確認してください。", "xpack.datasetQuality.emptyState.noPrivileges.title": "データセットを読み込めませんでした", - "xpack.datasetQuality.expandLabel": "拡張", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "データセット詳細を取得できませんでした。", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "データセットが選択されていません", "xpack.datasetQuality.fetchDatasetStatsFailed": "データセットを取得できませんでした。", "xpack.datasetQuality.fetchDegradedStatsFailed": "劣化したドキュメント情報を取得できませんでした。", "xpack.datasetQuality.fetchIntegrationsFailed": "統合を取得できませんでした。", @@ -14623,9 +14619,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "このデータセットの{degradedDocsCount}個の劣化したドキュメント。", "xpack.datasetQuality.filterBar.placeholder": "データセットのフィルタリング", "xpack.datasetQuality.flyout.degradedDocsTitle": "劣化したドキュメント", - "xpack.datasetQuality.flyout.degradedField.count": "ドキュメント数", - "xpack.datasetQuality.flyout.degradedField.field": "フィールド", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "前回の発生", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "今後の遅れを防止するには、手動でこのデータを{rolloverLink}してください。", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset}は_ignored集約をサポートしていません。データのクエリを実行するときに遅延が生じる可能性があります。{howToFixIt}", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 30cfd990ff4ee..9698931c132f7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -14625,7 +14625,6 @@ "xpack.datasetQuality.appTitle": "数据集质量", "xpack.datasetQuality.betaBadgeDescription": "此功能当前为公测版。如果遇到任何错误或有任何反馈,我们乐于倾听您的意见。请报告支持问题和/或访问我们的讨论论坛。", "xpack.datasetQuality.betaBadgeLabel": "公测版", - "xpack.datasetQuality.collapseLabel": "折叠", "xpack.datasetQuality.datasetQualityColumnName": "数据集质量", "xpack.datasetQuality.datasetQualityColumnTooltip": "质量基于数据集中的已降级文档的百分比。{visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14636,9 +14635,6 @@ "xpack.datasetQuality.emptyState.noData.title": "找不到数据集", "xpack.datasetQuality.emptyState.noPrivileges.message": "您没有查看日志数据所需的权限。请确保您具有足够的权限,可以查看 {datasetPattern}。", "xpack.datasetQuality.emptyState.noPrivileges.title": "无法加载数据集", - "xpack.datasetQuality.expandLabel": "展开", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "无法获取数据集详情。", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "尚未选择任何数据集", "xpack.datasetQuality.fetchDatasetStatsFailed": "无法获取数据集。", "xpack.datasetQuality.fetchDegradedStatsFailed": "无法获取已降级文档信息。", "xpack.datasetQuality.fetchIntegrationsFailed": "无法获取集成。", @@ -14646,9 +14642,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "此数据集中的 {degradedDocsCount} 个已降级文档。", "xpack.datasetQuality.filterBar.placeholder": "筛选数据集", "xpack.datasetQuality.flyout.degradedDocsTitle": "已降级文档", - "xpack.datasetQuality.flyout.degradedField.count": "文档计数", - "xpack.datasetQuality.flyout.degradedField.field": "字段", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "最后一次发生", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "手动 {rolloverLink} 此数据集以防止未来出现延迟。", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset} 不支持 _ignored 聚合,在查询数据时可能会导致延迟。{howToFixIt}", diff --git a/x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts b/x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts similarity index 69% rename from x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts rename to x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts index 52ccfad201a53..3ac6cf8b46945 100644 --- a/x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts +++ b/x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts @@ -10,6 +10,7 @@ import { DatasetQualityFtrProviderContext } from './config'; import { createDegradedFieldsRecord, datasetNames, + defaultNamespace, getInitialTestLogs, getLogsForDataset, productionNamespace, @@ -33,8 +34,9 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const retry = getService('retry'); const browser = getService('browser'); const to = '2024-01-01T12:00:00.000Z'; + const apacheAccessDatasetName = 'apache.access'; - const apacheAccessDatasetHumanName = 'Apache access logs'; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${productionNamespace}`; const apacheIntegrationId = 'apache'; const apachePkg = { name: 'apache', @@ -42,15 +44,18 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid }; const bitbucketDatasetName = 'atlassian_bitbucket.audit'; - const bitbucketDatasetHumanName = 'Bitbucket Audit Logs'; + const bitbucketAuditDataStreamName = `logs-${bitbucketDatasetName}-${defaultNamespace}`; const bitbucketPkg = { name: 'atlassian_bitbucket', version: '1.14.0', }; + const regularDatasetName = datasetNames[0]; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; const degradedDatasetName = datasetNames[2]; + const degradedDataStreamName = `logs-${degradedDatasetName}-${defaultNamespace}`; - describe('Flyout', () => { + describe('Dataset Quality Details', () => { before(async () => { // Install Apache Integration and ingest logs for it await PageObjects.observabilityLogsExplorer.installPackage(apachePkg); @@ -85,8 +90,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid // Index logs for Bitbucket integration getLogsForDataset({ to, count: 10, dataset: bitbucketDatasetName }), ]); - - await PageObjects.datasetQuality.navigateTo(); }); after(async () => { @@ -95,21 +98,49 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid await synthtrace.clean(); }); - describe('open flyout', () => { - it('should open the flyout for the right dataset', async () => { - const testDatasetName = datasetNames[1]; + describe('navigate to dataset details', () => { + it('should navigate to right dataset', async () => { + await PageObjects.datasetQuality.navigateToDetails({ dataStream: regularDataStreamName }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); + + it('should navigate to details page from a main page', async () => { + await PageObjects.datasetQuality.navigateTo(); + + const synthDataset = await testSubjects.find( + 'datasetQualityTableDetailsLink-logs-synth.1-default', + 20 * 1000 + ); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await synthDataset.click(); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutTitle + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle ); + }); - await PageObjects.datasetQuality.closeFlyout(); + it('should show an empty prompt with error message when the dataset is not found', async () => { + const nonExistentDataStreamName = 'logs-non.existent-production'; + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: nonExistentDataStreamName, + }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPrompt + ); + + const emptyPromptBody = await testSubjects.getVisibleText( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPromptBody + ); + + expect(emptyPromptBody).to.contain(nonExistentDataStreamName); }); it('reflects the breakdown field state in url', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ dataStream: degradedDataStreamName }); const breakdownField = 'service.name'; await PageObjects.datasetQuality.selectBreakdownField(breakdownField); @@ -128,46 +159,72 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.not.contain('breakdownField'); }); - await PageObjects.datasetQuality.closeFlyout(); }); }); - describe('integrations', () => { - it('should hide the integration section for non integrations', async () => { - const testDatasetName = datasetNames[1]; + describe('overview summary panel', () => { + it('should show summary KPIs', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + const { docsCountTotal, degradedDocs, services, hosts, size } = + await PageObjects.datasetQuality.parseOverviewSummaryPanelKpis(); + expect(parseInt(docsCountTotal, 10)).to.be(226); + expect(parseInt(degradedDocs, 10)).to.be(1); + expect(parseInt(services, 10)).to.be(3); + expect(parseInt(hosts, 10)).to.be(52); + expect(parseInt(size, 10)).to.be.greaterThan(0); + }); + }); + describe('overview integrations', () => { + it('should hide the integration section for non integrations', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); + + // The Integration row should not be present await testSubjects.missingOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration ); - await PageObjects.datasetQuality.closeFlyout(); + // The Version row should not be present + await testSubjects.missingOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion + ); }); it('should shows the integration section for integrations', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await testSubjects.existOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration + ); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion ); await retry.tryForTime(5000, async () => { const integrationNameExists = await PageObjects.datasetQuality.doesTextExist( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails, + .datasetQualityDetailsIntegrationRowIntegration, apacheIntegrationId ); expect(integrationNameExists).to.be(true); }); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the integration actions menu with correct actions', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); const actions = await Promise.all( @@ -177,23 +234,26 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid ); expect(actions.length).to.eql(3); - await PageObjects.datasetQuality.closeFlyout(); }); it('should hide integration dashboard for integrations without dashboards', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( integrationActions.viewDashboards ) ); - await PageObjects.datasetQuality.closeFlyout(); }); it('Should navigate to integration overview page on clicking integration overview action', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -208,12 +268,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid expect(parsedUrl.pathname).to.contain('/app/integrations/detail/atlassian_bitbucket'); }); - - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to index template page in clicking Integration template', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -229,11 +289,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid `/app/management/data/index_management/templates/logs-${apacheAccessDatasetName}` ); }); - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to the selected dashboard on clicking integration dashboard action ', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -251,119 +312,87 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const breadcrumbText = await testSubjects.getVisibleText('breadcrumb last'); expect(breadcrumbText).to.eql(dashboardText); - - await PageObjects.datasetQuality.navigateTo(); - }); - }); - - describe('summary panel', () => { - it('should show summary KPIs', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const { docsCountTotal, degradedDocs, services, hosts, size } = - await PageObjects.datasetQuality.parseFlyoutKpis(); - expect(parseInt(docsCountTotal, 10)).to.be(226); - expect(parseInt(degradedDocs, 10)).to.be(1); - expect(parseInt(services, 10)).to.be(3); - expect(parseInt(hosts, 10)).to.be(52); - expect(parseInt(size, 10)).to.be.greaterThan(0); - - await PageObjects.datasetQuality.closeFlyout(); }); }); describe('navigation', () => { - afterEach(async () => { - // Navigate back to dataset quality page after each test - await PageObjects.datasetQuality.navigateTo(); - }); - it('should go to log explorer page when the open in log explorer button is clicked', async () => { - const testDatasetName = datasetNames[2]; - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); - const logExplorerButton = await PageObjects.datasetQuality.getFlyoutLogsExplorerButton(); + const logExplorerButton = + await PageObjects.datasetQuality.getDatasetQualityDetailsHeaderButton(); await logExplorerButton.click(); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); - expect(datasetSelectorText).to.eql(testDatasetName); + expect(datasetSelectorText).to.eql(regularDatasetName); }); - it('should go log explorer for degraded docs when the show all button is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + it('should go log explorer for degraded docs when the button next to breakdown selector is clicked', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - const degradedDocsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.degradedDocs}`; - await testSubjects.click(degradedDocsShowAllSelector); + await testSubjects.click( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsLinkToDiscover + ); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); expect(datasetSelectorText).to.contain(apacheAccessDatasetName); }); - - // Blocked by https://github.com/elastic/kibana/issues/181705 - // Its a test written ahead of its time. - it.skip('goes to infra hosts for hosts when show all is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const hostsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.hosts}`; - await testSubjects.click(hostsShowAllSelector); - - // Confirm url contains metrics/hosts - await retry.tryForTime(5000, async () => { - const currentUrl = await browser.getCurrentUrl(); - const parsedUrl = new URL(currentUrl); - expect(parsedUrl.pathname).to.contain('/app/metrics/hosts'); - }); - }); }); describe('degraded fields table', () => { it(' should show empty degraded fields table when no degraded fields are present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(datasetNames[0]); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedTableNoData + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedTableNoData ); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the degraded fields table with data when present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); expect(rows.length).to.eql(2); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should display Spark Plot for every row of degraded fields', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); const sparkPlots = await testSubjects.findAll( PageObjects.datasetQuality.testSubjectSelectors.datasetQualitySparkPlot ); expect(rows.length).to.be(sparkPlots.length); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should sort the table when the count table header is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -374,12 +403,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const sortedCellTexts = await countColumn.getCellTexts(); expect(cellTexts.reverse()).to.eql(sortedCellTexts); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should update the URL when the table is sorted', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); const countColumn = table['Docs count']; @@ -405,8 +434,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid 'sort:(direction:asc,field:count)' ); }); - - await PageObjects.datasetQuality.closeFlyout(); }); // This is the only test which ingest data during the test. @@ -414,7 +441,9 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid // Even though this test ingest data, it can also be freely moved inside // this describe block, and it won't affect any of the existing tests it('should update the table when new data is ingested and the flyout is refreshed using the time selector', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -429,7 +458,7 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid }), ]); - await PageObjects.datasetQuality.refreshFlyout(); + await PageObjects.datasetQuality.refreshDetailsPageData(); const updatedTable = await PageObjects.datasetQuality.parseDegradedFieldTable(); const updatedCountColumn = updatedTable['Docs count']; @@ -440,8 +469,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const singleValueNow = parseInt(updatedCellTexts[0], 10); expect(singleValueNow).to.be.greaterThan(singleValuePreviously); - - await PageObjects.datasetQuality.closeFlyout(); }); }); }); diff --git a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts index c7c3cbf709931..c94a083946066 100644 --- a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts +++ b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { DatasetQualityFtrProviderContext } from './config'; -import { getInitialTestLogs, getLogsForDataset } from './data'; +import { datasetNames, defaultNamespace, getInitialTestLogs, getLogsForDataset } from './data'; export default function ({ getService, getPageObjects }: DatasetQualityFtrProviderContext) { const PageObjects = getPageObjects([ @@ -25,6 +25,8 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const apacheAccessDatasetName = 'apache.access'; const apacheAccessDatasetHumanName = 'Apache access logs'; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${defaultNamespace}`; describe('Dataset quality handles user privileges', () => { before(async () => { @@ -170,35 +172,39 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid ); }); - it('flyout shows insufficient privileges warning for underprivileged data stream', async () => { - await PageObjects.datasetQuality.openDatasetFlyout('synth.1'); + it('Details page shows insufficient privileges warning for underprivileged data stream', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityInsufficientPrivileges}-Size` ); - await PageObjects.datasetQuality.closeFlyout(); + await PageObjects.datasetQuality.navigateTo(); }); it('"View dashboards" and "See integration" are hidden for underprivileged user', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); // "See Integration" is hidden await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( 'Overview' ) ); // "View Dashboards" is hidden await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( 'ViewDashboards' ) ); - await PageObjects.datasetQuality.closeFlyout(); + await PageObjects.datasetQuality.navigateTo(); }); }); }); diff --git a/x-pack/test/functional/apps/dataset_quality/index.ts b/x-pack/test/functional/apps/dataset_quality/index.ts index f22af151ca6c9..ec975f6cafff6 100644 --- a/x-pack/test/functional/apps/dataset_quality/index.ts +++ b/x-pack/test/functional/apps/dataset_quality/index.ts @@ -13,7 +13,7 @@ export default function ({ loadTestFile }: DatasetQualityFtrProviderContext) { loadTestFile(require.resolve('./dataset_quality_summary')); loadTestFile(require.resolve('./dataset_quality_table')); loadTestFile(require.resolve('./dataset_quality_table_filters')); - loadTestFile(require.resolve('./dataset_quality_flyout')); loadTestFile(require.resolve('./dataset_quality_privileges')); + loadTestFile(require.resolve('./dataset_quality_details')); }); } diff --git a/x-pack/test/functional/page_objects/dataset_quality.ts b/x-pack/test/functional/page_objects/dataset_quality.ts index b2d07161ddbaa..8fdc021af79fc 100644 --- a/x-pack/test/functional/page_objects/dataset_quality.ts +++ b/x-pack/test/functional/page_objects/dataset_quality.ts @@ -7,12 +7,11 @@ import querystring from 'querystring'; import rison from '@kbn/rison'; -import expect from '@kbn/expect'; -import { TimeUnitId } from '@elastic/eui'; import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { DATA_QUALITY_URL_STATE_KEY, datasetQualityUrlSchemaV1, + datasetQualityDetailsUrlSchemaV1, } from '@kbn/data-quality-plugin/common'; import { DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, @@ -26,15 +25,18 @@ const defaultPageState: datasetQualityUrlSchemaV1.UrlSchema = { page: 0, }, filters: {}, - flyout: { - degradedFields: { - table: { - page: 0, - rowsPerPage: 10, - sort: { - field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, +}; + +const defaultDetailsPageState: datasetQualityDetailsUrlSchemaV1.UrlSchema = { + v: 1, + dataStream: 'logs-synth.1-default', + degradedFields: { + table: { + page: 0, + rowsPerPage: 10, + sort: { + field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, + direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, }, }, }, @@ -49,7 +51,10 @@ type SummaryPanelKpi = Record< string >; -type FlyoutKpi = Record<'docsCountTotal' | 'size' | 'services' | 'hosts' | 'degradedDocs', string>; +type SummaryPanelKPI = Record< + 'docsCountTotal' | 'size' | 'services' | 'hosts' | 'degradedDocs', + string +>; const texts = { noActivityText: 'No activity in the selected timeframe', @@ -58,7 +63,7 @@ const texts = { datasetHealthGood: 'Good', activeDatasets: 'Active Data Sets', estimatedData: 'Estimated Data', - docsCountTotal: 'Docs count (total)', + docsCountTotal: 'Total count', size: 'Size', services: 'Services', hosts: 'Hosts', @@ -86,20 +91,16 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv datasetQualityTable: 'datasetQualityTable', datasetQualityFiltersContainer: 'datasetQualityFiltersContainer', datasetQualityExpandButton: 'datasetQualityExpandButton', - datasetQualityFlyout: 'datasetQualityFlyout', - datasetQualityFlyoutBody: 'datasetQualityFlyoutBody', - datasetQualityFlyoutTitle: 'datasetQualityFlyoutTitle', - datasetQualityFlyoutDegradedFieldTable: 'datasetQualityFlyoutDegradedFieldTable', - datasetQualityFlyoutDegradedTableNoData: 'datasetQualityFlyoutDegradedTableNoData', + datasetDetailsContainer: 'datasetDetailsContainer', + datasetQualityDetailsTitle: 'datasetQualityDetailsTitle', + datasetQualityDetailsDegradedFieldTable: 'datasetQualityDetailsDegradedFieldTable', + datasetQualityDetailsDegradedTableNoData: 'datasetQualityDetailsDegradedTableNoData', datasetQualitySparkPlot: 'datasetQualitySparkPlot', - datasetQualityHeaderButton: 'datasetQualityHeaderButton', - datasetQualityFlyoutFieldValue: 'datasetQualityFlyoutFieldValue', - datasetQualityFlyoutFieldsListIntegrationDetails: - 'datasetQualityFlyoutFieldsList-integration_details', - datasetQualityFlyoutIntegrationLoading: 'datasetQualityFlyoutIntegrationLoading', - datasetQualityFlyoutIntegrationActionsButton: 'datasetQualityFlyoutIntegrationActionsButton', - datasetQualityFlyoutIntegrationAction: (action: string) => - `datasetQualityFlyoutIntegrationAction${action}`, + datasetQualityDetailsHeaderButton: 'datasetQualityDetailsHeaderButton', + datasetQualityDetailsIntegrationLoading: 'datasetQualityDetailsIntegrationLoading', + datasetQualityDetailsIntegrationActionsButton: 'datasetQualityDetailsIntegrationActionsButton', + datasetQualityDetailsIntegrationAction: (action: string) => + `datasetQualityDetailsIntegrationAction${action}`, datasetQualityFilterBarFieldSearch: 'datasetQualityFilterBarFieldSearch', datasetQualityIntegrationsSelectable: 'datasetQualityIntegrationsSelectable', datasetQualityIntegrationsSelectableButton: 'datasetQualityIntegrationsSelectableButton', @@ -107,9 +108,13 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv datasetQualityNamespacesSelectableButton: 'datasetQualityNamespacesSelectableButton', datasetQualityQualitiesSelectable: 'datasetQualityQualitiesSelectable', datasetQualityQualitiesSelectableButton: 'datasetQualityQualitiesSelectableButton', + datasetQualityDetailsEmptyPrompt: 'datasetQualityDetailsEmptyPrompt', + datasetQualityDetailsEmptyPromptBody: 'datasetQualityDetailsEmptyPromptBody', datasetQualityDatasetHealthKpi: 'datasetQualityDatasetHealthKpi', - datasetQualityFlyoutKpiValue: 'datasetQualityFlyoutKpiValue', - datasetQualityFlyoutKpiLink: 'datasetQualityFlyoutKpiLink', + datasetQualityDetailsSummaryKpiValue: 'datasetQualityDetailsSummaryKpiValue', + datasetQualityDetailsIntegrationRowIntegration: 'datasetQualityDetailsFieldsList-integration', + datasetQualityDetailsIntegrationRowVersion: 'datasetQualityDetailsFieldsList-version', + datasetQualityDetailsLinkToDiscover: 'datasetQualityDetailsLinkToDiscover', datasetQualityInsufficientPrivileges: 'datasetQualityInsufficientPrivileges', datasetQualityNoDataEmptyState: 'datasetQualityNoDataEmptyState', datasetQualityNoPrivilegesEmptyState: 'datasetQualityNoPrivilegesEmptyState', @@ -117,7 +122,6 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv superDatePickerToggleQuickMenuButton: 'superDatePickerToggleQuickMenuButton', superDatePickerApplyTimeButton: 'superDatePickerApplyTimeButton', superDatePickerQuickMenu: 'superDatePickerQuickMenu', - euiFlyoutCloseButton: 'euiFlyoutCloseButton', unifiedHistogramBreakdownSelectorButton: 'unifiedHistogramBreakdownSelectorButton', unifiedHistogramBreakdownSelectorSelectorSearch: 'unifiedHistogramBreakdownSelectorSelectorSearch', @@ -156,19 +160,30 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv ); }, - async waitUntilTableLoaded() { - await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 20 * 1000); - }, + async navigateToDetails(pageState: datasetQualityDetailsUrlSchemaV1.UrlSchema) { + const queryStringParams = querystring.stringify({ + [DATA_QUALITY_URL_STATE_KEY]: rison.encode( + datasetQualityDetailsUrlSchemaV1.urlSchemaRT.encode({ + ...defaultDetailsPageState, + ...pageState, + }) + ), + }); - async waitUntilTableInFlyoutLoaded() { - await find.waitForDeletedByCssSelector('.euiFlyoutBody .euiBasicTable-loading', 20 * 1000); + return PageObjects.common.navigateToUrlWithBrowserHistory( + 'management', + '/data/data_quality/details', + queryStringParams, + { + // the check sometimes is too slow for the page so it misses the point + // in time before the app rewrites the URL + ensureCurrentUrl: false, + } + ); }, - async waitUntilIntegrationsInFlyoutLoaded() { - await find.waitForDeletedByCssSelector( - '.euiSkeletonTitle .datasetQualityFlyoutIntegrationLoading', - 10 * 1000 - ); + async waitUntilTableLoaded() { + await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 20 * 1000); }, async waitUntilSummaryPanelLoaded(isStateful: boolean = true) { @@ -213,14 +228,14 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return testSubjects.find(testSubjectSelectors.datasetQualityTable); }, - getDatasetQualityFlyoutDegradedFieldTable(): Promise { - return testSubjects.find(testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable); + getDatasetQualityDetailsDegradedFieldTable(): Promise { + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsDegradedFieldTable); }, - async getDatasetQualityFlyoutDegradedFieldTableRows(): Promise { - await this.waitUntilTableInFlyoutLoaded(); + async getDatasetQualityDetailsDegradedFieldTableRows(): Promise { + await this.waitUntilTableLoaded(); const table = await testSubjects.find( - testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const tBody = await table.findByTagName('tbody'); return tBody.findAllByTagName('tr'); @@ -265,8 +280,8 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv }, async parseDegradedFieldTable() { - await this.waitUntilTableInFlyoutLoaded(); - const table = await this.getDatasetQualityFlyoutDegradedFieldTable(); + await this.waitUntilTableLoaded(); + const table = await this.getDatasetQualityDetailsDegradedFieldTable(); return this.parseTable(table, ['Field', 'Docs count', 'Last Occurrence']); }, @@ -302,46 +317,11 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return find.clickByCssSelector(selectors.showFullDatasetNamesSwitch); }, - async openDatasetFlyout(datasetName: string) { - await this.waitUntilTableLoaded(); - const cols = await this.parseDatasetTable(); - const datasetNameCol = cols['Data Set Name']; - const datasetNameColCellTexts = await datasetNameCol.getCellTexts(); - const testDatasetRowIndex = datasetNameColCellTexts.findIndex( - (dName) => dName === datasetName + async refreshDetailsPageData() { + const datasetDetailsContainer: WebElementWrapper = await testSubjects.find( + testSubjectSelectors.datasetDetailsContainer ); - - expect(testDatasetRowIndex).to.be.greaterThan(-1); - - const expandColumn = cols['0']; - const expandButtons = await expandColumn.getCellChildren( - `[data-test-subj=${testSubjectSelectors.datasetQualityExpandButton}]` - ); - - expect(expandButtons.length).to.be.greaterThan(0); - - const datasetExpandButton = expandButtons[testDatasetRowIndex]; - - // Check if 'title' attribute is "Expand" or "Collapse" - const isCollapsed = (await datasetExpandButton.getAttribute('title')) === 'Expand'; - - // Open if collapsed - if (isCollapsed) { - await datasetExpandButton.click(); - } - - await this.waitUntilIntegrationsInFlyoutLoaded(); - }, - - async closeFlyout() { - return testSubjects.click(testSubjectSelectors.euiFlyoutCloseButton); - }, - - async refreshFlyout() { - const flyoutContainer: WebElementWrapper = await testSubjects.find( - testSubjectSelectors.datasetQualityFlyoutBody - ); - const refreshButton = await flyoutContainer.findByTestSubject( + const refreshButton = await datasetDetailsContainer.findByTestSubject( testSubjectSelectors.superDatePickerApplyTimeButton ); return refreshButton.click(); @@ -357,27 +337,27 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return false; }, - getFlyoutLogsExplorerButton() { - return testSubjects.find(testSubjectSelectors.datasetQualityHeaderButton); + getDatasetQualityDetailsHeaderButton() { + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsHeaderButton); }, openIntegrationActionsMenu() { - return testSubjects.click(testSubjectSelectors.datasetQualityFlyoutIntegrationActionsButton); + return testSubjects.click(testSubjectSelectors.datasetQualityDetailsIntegrationActionsButton); }, getIntegrationActionButtonByAction(action: string) { - return testSubjects.find(testSubjectSelectors.datasetQualityFlyoutIntegrationAction(action)); + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsIntegrationAction(action)); }, getIntegrationDashboardButtons() { return testSubjects.findAll( - testSubjectSelectors.datasetQualityFlyoutIntegrationAction('Dashboard') + testSubjectSelectors.datasetQualityDetailsIntegrationAction('Dashboard') ); }, // `excludeKeys` needed to circumvent `_stats` not available in Serverless https://github.com/elastic/kibana/issues/178954 // TODO: Remove `excludeKeys` when `_stats` is available in Serverless - async parseFlyoutKpis(excludeKeys: string[] = []): Promise { + async parseOverviewSummaryPanelKpis(excludeKeys: string[] = []): Promise { const kpiTitleAndKeys = [ { title: texts.docsCountTotal, key: 'docsCountTotal' }, { title: texts.size, key: 'size' }, @@ -390,7 +370,7 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv kpiTitleAndKeys.map(async ({ title, key }) => ({ key, value: await testSubjects.getVisibleText( - `${testSubjectSelectors.datasetQualityFlyoutKpiValue}-${title}` + `${testSubjectSelectors.datasetQualityDetailsSummaryKpiValue}-${title}` ), })) ); @@ -400,52 +380,10 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv ...acc, [key]: value, }), - {} as FlyoutKpi + {} as SummaryPanelKPI ); }, - async setDatePickerLastXUnits( - container: WebElementWrapper, - timeValue: number, - unit: TimeUnitId - ) { - // Only click the menu button found under the provided container - const datePickerToggleQuickMenuButton = await container.findByTestSubject( - testSubjectSelectors.superDatePickerToggleQuickMenuButton - ); - await datePickerToggleQuickMenuButton.click(); - - const datePickerQuickMenu = await testSubjects.find( - testSubjectSelectors.superDatePickerQuickMenu - ); - - const timeTenseSelect = await datePickerQuickMenu.findByCssSelector( - `select[aria-label="Time tense"]` - ); - const timeValueInput = await datePickerQuickMenu.findByCssSelector( - `input[aria-label="Time value"]` - ); - const timeUnitSelect = await datePickerQuickMenu.findByCssSelector( - `select[aria-label="Time unit"]` - ); - - await timeTenseSelect.focus(); - await timeTenseSelect.type('Last'); - - await timeValueInput.focus(); - await timeValueInput.clearValue(); - await timeValueInput.type(timeValue.toString()); - - await timeUnitSelect.focus(); - await timeUnitSelect.type(unit); - - await ( - await datePickerQuickMenu.findByCssSelector(selectors.superDatePickerApplyButton) - ).click(); - - return testSubjects.missingOrFail(testSubjectSelectors.superDatePickerQuickMenu); - }, - /** * Selects a breakdown field from the unified histogram breakdown selector * @param fieldText The text of the field to select. Use 'No breakdown' to clear the selection diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts similarity index 69% rename from x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts rename to x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts index fda145ebfea7f..bca31c506a770 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { defaultNamespace } from '@kbn/test-suites-xpack/functional/apps/dataset_quality/data'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { datasetNames, @@ -38,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const excludeKeysFromServerless = ['size']; // https://github.com/elastic/kibana/issues/178954 const apacheAccessDatasetName = 'apache.access'; - const apacheAccessDatasetHumanName = 'Apache access logs'; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${productionNamespace}`; const apacheIntegrationId = 'apache'; const apachePkg = { name: 'apache', @@ -46,13 +47,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; const bitbucketDatasetName = 'atlassian_bitbucket.audit'; - const bitbucketDatasetHumanName = 'Bitbucket Audit Logs'; + const bitbucketAuditDataStreamName = `logs-${bitbucketDatasetName}-${defaultNamespace}`; const bitbucketPkg = { name: 'atlassian_bitbucket', version: '1.14.0', }; + const regularDatasetName = datasetNames[0]; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; const degradedDatasetName = datasetNames[2]; + const degradedDataStreamName = `logs-${degradedDatasetName}-${defaultNamespace}`; describe('Flyout', function () { before(async () => { @@ -91,8 +95,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ]); await PageObjects.svlCommonPage.loginWithPrivilegedRole(); - - await PageObjects.datasetQuality.navigateTo(); }); after(async () => { @@ -101,21 +103,49 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await synthtrace.clean(); }); - describe('open flyout', () => { - it('should open the flyout for the right dataset', async () => { - const testDatasetName = datasetNames[1]; + describe('navigate to dataset details', () => { + it('should navigate to right dataset', async () => { + await PageObjects.datasetQuality.navigateToDetails({ dataStream: regularDataStreamName }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); + + it('should navigate to details page from a main page', async () => { + await PageObjects.datasetQuality.navigateTo(); + + const synthDataset = await testSubjects.find( + 'datasetQualityTableDetailsLink-logs-synth.1-default', + 20 * 1000 + ); + + await synthDataset.click(); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + it('should show an empty prompt with error message when the dataset is not found', async () => { + const nonExistentDataStreamName = 'logs-non.existent-production'; + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: nonExistentDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutTitle + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPrompt + ); + + const emptyPromptBody = await testSubjects.getVisibleText( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPromptBody ); - await PageObjects.datasetQuality.closeFlyout(); + expect(emptyPromptBody).to.contain(nonExistentDataStreamName); }); it('reflects the breakdown field state in url', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ dataStream: degradedDataStreamName }); const breakdownField = 'service.name'; await PageObjects.datasetQuality.selectBreakdownField(breakdownField); @@ -134,46 +164,71 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.not.contain('breakdownField'); }); - await PageObjects.datasetQuality.closeFlyout(); }); }); - describe('integrations', () => { - it('should hide the integration section for non integrations', async () => { - const testDatasetName = datasetNames[1]; + describe('overview summary panel', () => { + it('should show summary KPIs', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + const { docsCountTotal, degradedDocs, services, hosts } = + await PageObjects.datasetQuality.parseOverviewSummaryPanelKpis(excludeKeysFromServerless); + expect(parseInt(docsCountTotal, 10)).to.be(226); + expect(parseInt(degradedDocs, 10)).to.be(1); + expect(parseInt(services, 10)).to.be(3); + expect(parseInt(hosts, 10)).to.be(52); + }); + }); + describe('overview integrations', () => { + it('should hide the integration section for non integrations', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); + + // The Integration row should not be present await testSubjects.missingOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration ); - await PageObjects.datasetQuality.closeFlyout(); + // The Version row should not be present + await testSubjects.missingOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion + ); }); it('should shows the integration section for integrations', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await testSubjects.existOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration + ); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion ); await retry.tryForTime(5000, async () => { const integrationNameExists = await PageObjects.datasetQuality.doesTextExist( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails, + .datasetQualityDetailsIntegrationRowIntegration, apacheIntegrationId ); expect(integrationNameExists).to.be(true); }); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the integration actions menu with correct actions', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); const actions = await Promise.all( @@ -183,23 +238,26 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); expect(actions.length).to.eql(3); - await PageObjects.datasetQuality.closeFlyout(); }); it('should hide integration dashboard for integrations without dashboards', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( integrationActions.viewDashboards ) ); - await PageObjects.datasetQuality.closeFlyout(); }); it('Should navigate to integration overview page on clicking integration overview action', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -214,12 +272,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(parsedUrl.pathname).to.contain('/app/integrations/detail/atlassian_bitbucket'); }); - - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to index template page in clicking Integration template', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -235,11 +293,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { `/app/management/data/index_management/templates/logs-${apacheAccessDatasetName}` ); }); - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to the selected dashboard on clicking integration dashboard action ', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -257,118 +316,87 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const breadcrumbText = await testSubjects.getVisibleText('breadcrumb last'); expect(breadcrumbText).to.eql(dashboardText); - - await PageObjects.datasetQuality.navigateTo(); - }); - }); - - describe('summary panel', () => { - it('should show summary KPIs', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const { docsCountTotal, degradedDocs, services, hosts } = - await PageObjects.datasetQuality.parseFlyoutKpis(excludeKeysFromServerless); - expect(parseInt(docsCountTotal, 10)).to.be(226); - expect(parseInt(degradedDocs, 10)).to.be(1); - expect(parseInt(services, 10)).to.be(3); - expect(parseInt(hosts, 10)).to.be(52); - - await PageObjects.datasetQuality.closeFlyout(); }); }); describe('navigation', () => { - afterEach(async () => { - // Navigate back to dataset quality page after each test - await PageObjects.datasetQuality.navigateTo(); - }); - it('should go to log explorer page when the open in log explorer button is clicked', async () => { - const testDatasetName = datasetNames[2]; - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); - const logExplorerButton = await PageObjects.datasetQuality.getFlyoutLogsExplorerButton(); + const logExplorerButton = + await PageObjects.datasetQuality.getDatasetQualityDetailsHeaderButton(); await logExplorerButton.click(); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); - expect(datasetSelectorText).to.eql(testDatasetName); + expect(datasetSelectorText).to.eql(regularDatasetName); }); - it('should go log explorer for degraded docs when the show all button is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + it('should go log explorer for degraded docs when the button next to breakdown selector is clicked', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - const degradedDocsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.degradedDocs}`; - await testSubjects.click(degradedDocsShowAllSelector); + await testSubjects.click( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsLinkToDiscover + ); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); expect(datasetSelectorText).to.contain(apacheAccessDatasetName); }); - - // Blocked by https://github.com/elastic/kibana/issues/181705 - // Its a test written ahead of its time. - it.skip('goes to infra hosts for hosts when show all is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const hostsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.hosts}`; - await testSubjects.click(hostsShowAllSelector); - - // Confirm url contains metrics/hosts - await retry.tryForTime(5000, async () => { - const currentUrl = await browser.getCurrentUrl(); - const parsedUrl = new URL(currentUrl); - expect(parsedUrl.pathname).to.contain('/app/metrics/hosts'); - }); - }); }); describe('degraded fields table', () => { it(' should show empty degraded fields table when no degraded fields are present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(datasetNames[0]); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedTableNoData + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedTableNoData ); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the degraded fields table with data when present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); expect(rows.length).to.eql(2); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should display Spark Plot for every row of degraded fields', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); const sparkPlots = await testSubjects.findAll( PageObjects.datasetQuality.testSubjectSelectors.datasetQualitySparkPlot ); expect(rows.length).to.be(sparkPlots.length); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should sort the table when the count table header is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -379,12 +407,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const sortedCellTexts = await countColumn.getCellTexts(); expect(cellTexts.reverse()).to.eql(sortedCellTexts); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should update the URL when the table is sorted', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); const countColumn = table['Docs count']; @@ -410,8 +438,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'sort:(direction:asc,field:count)' ); }); - - await PageObjects.datasetQuality.closeFlyout(); }); // This is the only test which ingest data during the test. @@ -419,7 +445,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Even though this test ingest data, it can also be freely moved inside // this describe block, and it won't affect any of the existing tests it('should update the table when new data is ingested and the flyout is refreshed using the time selector', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -434,7 +462,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }), ]); - await PageObjects.datasetQuality.refreshFlyout(); + await PageObjects.datasetQuality.refreshDetailsPageData(); const updatedTable = await PageObjects.datasetQuality.parseDegradedFieldTable(); const updatedCountColumn = updatedTable['Docs count']; @@ -445,8 +473,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const singleValueNow = parseInt(updatedCellTexts[0], 10); expect(singleValueNow).to.be.greaterThan(singleValuePreviously); - - await PageObjects.datasetQuality.closeFlyout(); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts index 30547ceb941b3..683c879ae4e3d 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts @@ -13,7 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dataset_quality_summary')); loadTestFile(require.resolve('./dataset_quality_table')); loadTestFile(require.resolve('./dataset_quality_table_filters')); - loadTestFile(require.resolve('./dataset_quality_flyout')); loadTestFile(require.resolve('./dataset_quality_privileges')); + loadTestFile(require.resolve('./dataset_quality_details')); }); } From 9372027e6c74f62d8ffc8d7539bdc2d27d1c0e05 Mon Sep 17 00:00:00 2001 From: Ersin Erdal <92688503+ersin-erdal@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:48:29 +0300 Subject: [PATCH 25/38] Metering connector actions request body bytes (#186804) Towards: https://github.com/elastic/response-ops-team/issues/209 This PR collects body-bytes from the requests made by the connectors to the 3rd parties and saves them in the event-log. There is a new metric collector: `ConnectorMetricsCollector` Action TaskRunner, creates a new instance of it on each action execution and passes it to the actionType.executor. Then the actionType.executor passes it to the request function provided by the actions plugin. Request function passes the response (or the error) from axios to `addRequestBodyBytes` method of the `ConnectorMetricsCollector`. Since axios always returns `request.headers['Content-Length']` either in success result or error, metric collector uses its value to get the request body bytes. In case there is no `Content-Length` header, `addRequestBodyBytes` method fallbacks to the body object that we pass as the second param. So It calculates the body bytes by using `Buffer.byteLength(body, 'utf8');`, which is also used by axios to populate `request.headers['Content-Length']` For the connectors or the subActions that we don't use the request function or axios: addRequestBodyBytes method is called just before making the request only with the body param in order to force it to use the fallback. Note: If there are more than one requests in an execution, the bytes are summed. ## To verify: Create a rule with a connector that you would like to test. Let the rule run and check the event-log of your connector, request body bytes should be saved in: `kibana.action.execution.metrics.request_body_bytes` Alternatively: You can create a connector and run it on its test tab. You can use the below query to check the event-log: ``` { "query": { "bool": { "must": [ { "match": { "event.provider":"actions"}}, { "match": { "kibana.action.type_id":"{**your-action-type-id**}"}} ], "filter": [ { "term": { "event.action": "execute" }} ] } }, "size" : 100 } ``` --- .../server/lib/action_executor.test.ts | 65 +- .../actions/server/lib/action_executor.ts | 20 +- .../actions/server/lib/axios_utils.test.ts | 77 +- .../plugins/actions/server/lib/axios_utils.ts | 44 +- ...ate_action_event_log_record_object.test.ts | 16 + .../create_action_event_log_record_object.ts | 3 + .../server/sub_action_framework/case.test.ts | 61 +- .../server/sub_action_framework/case.ts | 123 ++-- .../sub_action_framework/executor.test.ts | 56 ++ .../server/sub_action_framework/executor.ts | 12 +- .../server/sub_action_framework/mocks.ts | 63 +- .../sub_action_connector.test.ts | 72 +- .../sub_action_connector.ts | 23 +- x-pack/plugins/actions/server/types.ts | 7 +- .../unsecured_actions_client.ts | 7 +- .../usage/connector_usage_collector.test.ts | 102 +++ .../server/usage/connector_usage_collector.ts | 52 ++ x-pack/plugins/actions/server/usage/index.ts | 1 + .../plugins/event_log/generated/mappings.json | 11 + x-pack/plugins/event_log/generated/schemas.ts | 6 + x-pack/plugins/event_log/scripts/mappings.js | 11 + .../connector_types/bedrock/bedrock.test.ts | 685 ++++++++++-------- .../server/connector_types/bedrock/bedrock.ts | 196 ++--- .../connector_types/cases_webhook/index.ts | 5 +- .../cases_webhook/service.test.ts | 138 +++- .../connector_types/cases_webhook/service.ts | 8 +- .../crowdstrike/crowdstrike.test.ts | 76 +- .../crowdstrike/crowdstrike.ts | 139 ++-- .../d3security/d3security.test.ts | 35 +- .../connector_types/d3security/d3security.ts | 35 +- .../connector_types/email/index.test.ts | 7 + .../server/connector_types/email/index.ts | 19 +- .../connector_types/email/send_email.test.ts | 111 ++- .../connector_types/email/send_email.ts | 27 +- .../email/send_email_graph_api.test.ts | 31 +- .../email/send_email_graph_api.ts | 15 +- .../connector_types/es_index/index.test.ts | 14 + .../connector_types/gemini/gemini.test.ts | 269 +++---- .../server/connector_types/gemini/gemini.ts | 140 ++-- .../server/connector_types/jira/index.ts | 13 +- .../connector_types/jira/service.test.ts | 39 +- .../server/connector_types/jira/service.ts | 14 +- .../servicenow/create_service_wrapper.test.ts | 10 + .../lib/servicenow/create_service_wrapper.ts | 8 +- .../lib/servicenow/service.test.ts | 58 ++ .../connector_types/lib/servicenow/service.ts | 9 + .../connector_types/lib/servicenow/types.ts | 4 +- .../connector_types/openai/openai.test.ts | 667 ++++++++++------- .../server/connector_types/openai/openai.ts | 110 +-- .../opsgenie/connector.test.ts | 24 +- .../connector_types/opsgenie/connector.ts | 45 +- .../connector_types/pagerduty/index.test.ts | 19 +- .../server/connector_types/pagerduty/index.ts | 15 +- .../pagerduty/post_pagerduty.ts | 6 +- .../resilient/resilient.test.ts | 96 ++- .../connector_types/resilient/resilient.ts | 167 +++-- .../sentinelone/sentinelone.test.ts | 43 +- .../sentinelone/sentinelone.ts | 266 ++++--- .../connector_types/server_log/index.test.ts | 5 + .../connector_types/servicenow_itom/index.ts | 11 +- .../servicenow_itom/service.test.ts | 9 + .../servicenow_itom/service.ts | 3 + .../connector_types/servicenow_itsm/index.ts | 13 +- .../servicenow_itsm/service.test.ts | 39 + .../connector_types/servicenow_sir/index.ts | 13 +- .../servicenow_sir/service.test.ts | 9 + .../connector_types/servicenow_sir/service.ts | 3 + .../connector_types/slack/index.test.ts | 13 + .../server/connector_types/slack/index.ts | 4 +- .../connector_types/slack_api/index.test.ts | 16 +- .../server/connector_types/slack_api/index.ts | 4 +- .../connector_types/slack_api/service.test.ts | 19 +- .../connector_types/slack_api/service.ts | 7 +- .../server/connector_types/swimlane/index.ts | 13 +- .../connector_types/swimlane/service.test.ts | 24 +- .../connector_types/swimlane/service.ts | 7 +- .../connector_types/teams/index.test.ts | 69 +- .../server/connector_types/teams/index.ts | 4 +- .../connector_types/thehive/thehive.test.ts | 156 ++-- .../server/connector_types/thehive/thehive.ts | 119 +-- .../connector_types/tines/tines.test.ts | 55 +- .../server/connector_types/tines/tines.ts | 57 +- .../torq/__snapshots__/index.test.ts.snap | 48 ++ .../server/connector_types/torq/index.test.ts | 63 +- .../server/connector_types/torq/index.ts | 2 + .../webhook/__snapshots__/index.test.ts.snap | 46 ++ .../connector_types/webhook/index.test.ts | 123 +++- .../server/connector_types/webhook/index.ts | 4 +- .../connector_types/xmatters/index.test.ts | 10 +- .../server/connector_types/xmatters/index.ts | 12 +- .../connector_types/xmatters/post_xmatters.ts | 5 +- .../alerts/server/sub_action_connector.ts | 7 +- .../tests/actions/connector_types/bedrock.ts | 54 +- .../actions/connector_types/cases_webhook.ts | 20 + .../actions/connector_types/d3security.ts | 21 + .../tests/actions/connector_types/email.ts | 22 +- .../tests/actions/connector_types/es_index.ts | 20 + .../tests/actions/connector_types/jira.ts | 20 + .../tests/actions/connector_types/openai.ts | 19 + .../tests/actions/connector_types/opsgenie.ts | 20 + .../actions/connector_types/pagerduty.ts | 20 + .../actions/connector_types/resilient.ts | 20 + .../actions/connector_types/server_log.ts | 20 + .../connector_types/servicenow_itom.ts | 37 + .../connector_types/servicenow_itsm.ts | 70 ++ .../actions/connector_types/servicenow_sir.ts | 53 ++ .../actions/connector_types/slack_webhook.ts | 21 + .../tests/actions/connector_types/swimlane.ts | 37 + .../tests/actions/connector_types/tines.ts | 84 +++ .../tests/actions/connector_types/torq.ts | 19 + .../tests/actions/connector_types/webhook.ts | 21 + .../tests/actions/connector_types/xmatters.ts | 20 + .../group2/tests/actions/execute.ts | 2 + .../actions/sub_action_framework/index.ts | 30 +- 114 files changed, 4347 insertions(+), 1690 deletions(-) create mode 100644 x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts create mode 100644 x-pack/plugins/actions/server/usage/connector_usage_collector.ts create mode 100644 x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap create mode 100644 x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index b2e6badae3c59..560d5dc3ecea5 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { KibanaRequest } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { ActionExecutor } from './action_executor'; @@ -18,7 +17,7 @@ import { } from '@kbn/core/server/mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/mocks'; import { spacesServiceMock } from '@kbn/spaces-plugin/server/spaces_service/spaces_service.mock'; -import { ActionType as ConnectorType } from '../types'; +import { ActionType as ConnectorType, ConnectorUsageCollector } from '../types'; import { actionsAuthorizationMock, actionsMock } from '../mocks'; import { asBackgroundTaskExecutionSource, @@ -150,6 +149,10 @@ const connectorSavedObject = { references: [], }; +interface ActionUsage { + request_body_bytes: number; +} + const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { return { event: { @@ -163,6 +166,7 @@ const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { }, id: CONNECTOR_ID, name: '1', + type_id: 'test', }, ...(unsecured ? {} @@ -190,10 +194,23 @@ const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { }; }; -const getBaseExecuteEventLogDoc = (unsecured: boolean) => { +const getBaseExecuteEventLogDoc = ( + unsecured: boolean, + actionUsage: ActionUsage = { request_body_bytes: 0 } +) => { const base = getBaseExecuteStartEventLogDoc(unsecured); return { ...base, + kibana: { + ...base.kibana, + action: { + ...base.kibana.action, + execution: { + ...base.kibana.action.execution, + usage: actionUsage, + }, + }, + }, event: { ...base.event, action: 'execute', @@ -211,9 +228,12 @@ const getBaseExecuteEventLogDoc = (unsecured: boolean) => { }; }; +const mockGetRequestBodyByte = jest.spyOn(ConnectorUsageCollector.prototype, 'getRequestBodyByte'); + beforeEach(() => { jest.resetAllMocks(); jest.clearAllMocks(); + mockGetRequestBodyByte.mockReturnValue(0); spacesMock.getSpaceId.mockReturnValue('some-namespace'); loggerMock.get.mockImplementation(() => loggerMock); const mockRealm = { name: 'default_native', type: 'native' }; @@ -237,6 +257,7 @@ describe('Action Executor', () => { const label = executeUnsecure ? 'executes unsecured' : 'executes'; test(`successfully ${label}`, async () => { + mockGetRequestBodyByte.mockReturnValue(300); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( connectorSavedObject ); @@ -280,13 +301,15 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:1: 1'); expect(eventLogger.logEvent).toHaveBeenCalledTimes(2); const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); - const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + const execDoc = getBaseExecuteEventLogDoc(executeUnsecure, { request_body_bytes: 300 }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, execStartDoc); expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, execDoc); }); @@ -353,6 +376,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, source: executionSource.source, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:1: 1'); @@ -360,6 +384,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -431,6 +456,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:preconfigured: Preconfigured'); @@ -438,6 +464,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -513,6 +540,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); } @@ -532,6 +560,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -540,6 +569,7 @@ describe('Action Executor', () => { ...execStartDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -569,6 +599,7 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -890,6 +921,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -921,6 +953,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -989,6 +1022,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:preconfigured: Preconfigured'); @@ -996,6 +1030,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -1026,6 +1061,12 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'preconfigured', name: 'Preconfigured', + execution: { + ...execStartDoc.kibana.action.execution, + usage: { + request_body_bytes: 0, + }, + }, }, saved_objects: [ { @@ -1074,6 +1115,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith( @@ -1083,6 +1125,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -1091,6 +1134,7 @@ describe('Action Executor', () => { ...execStartDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -1120,6 +1164,7 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -1290,6 +1335,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); } }); @@ -1385,6 +1431,7 @@ describe('Event log', () => { }, name: undefined, id: 'action1', + type_id: 'test', }, alert: { rule: { @@ -1430,6 +1477,7 @@ describe('Event log', () => { }, name: 'action-1', id: '1', + type_id: 'test', }, alert: { rule: { @@ -1483,6 +1531,7 @@ describe('Event log', () => { }, name: 'action-1', id: '1', + type_id: 'test', }, alert: { rule: { @@ -1559,9 +1608,13 @@ describe('Event log', () => { gen_ai: { usage: mockGenAi.usage, }, + usage: { + request_body_bytes: 0, + }, }, name: 'action-1', id: '1', + type_id: '.gen-ai', }, alert: { rule: { @@ -1655,9 +1708,13 @@ describe('Event log', () => { total_tokens: 35, }, }, + usage: { + request_body_bytes: 0, + }, }, name: 'action-1', id: '1', + type_id: '.gen-ai', }, alert: { rule: { diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 685e18c585ae0..c302b0da3e886 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -23,6 +23,7 @@ import { IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/se import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/server'; import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; import { GEN_AI_TOKEN_COUNT_EVENT } from './event_based_telemetry'; +import { ConnectorUsageCollector } from '../usage/connector_usage_collector'; import { getGenAiTokenTracking, shouldTrackGenAiToken } from './gen_ai_token_tracking'; import { validateConfig, @@ -293,6 +294,7 @@ export class ActionExecutor { actionExecutionId, isInMemory: this.actionInfo.isInMemory, ...(source ? { source } : {}), + actionTypeId: this.actionInfo.actionTypeId, }); eventLogger.logEvent(event); @@ -394,6 +396,14 @@ export class ActionExecutor { const { actionTypeId, name, config, secrets } = actionInfo; + const loggerId = actionTypeId.startsWith('.') ? actionTypeId.substring(1) : actionTypeId; + const logger = this.actionExecutorContext!.logger.get(loggerId); + + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: actionId, + }); + if (!this.actionInfo || this.actionInfo.actionId !== actionId) { this.actionInfo = actionInfo; } @@ -434,9 +444,6 @@ export class ActionExecutor { return err.result; } - const loggerId = actionTypeId.startsWith('.') ? actionTypeId.substring(1) : actionTypeId; - const logger = this.actionExecutorContext!.logger.get(loggerId); - if (span) { span.name = `${executeLabel} ${actionTypeId}`; span.addLabels({ @@ -477,6 +484,7 @@ export class ActionExecutor { actionExecutionId, isInMemory: this.actionInfo.isInMemory, ...(source ? { source } : {}), + actionTypeId, }); eventLogger.startTiming(event); @@ -510,6 +518,7 @@ export class ActionExecutor { logger, source, ...(actionType.isSystemActionType ? { request } : {}), + connectorUsageCollector, }); if (rawResult && rawResult.status === 'error') { @@ -548,6 +557,11 @@ export class ActionExecutor { event.user = event.user || {}; event.user.name = currentUser?.username; event.user.id = currentUser?.profile_uid; + set( + event, + 'kibana.action.execution.usage.request_body_bytes', + connectorUsageCollector.getRequestBodyByte() + ); if (result.status === 'ok') { span?.setOutcome('success'); diff --git a/x-pack/plugins/actions/server/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/lib/axios_utils.test.ts index c5e23f6cd3db3..bee09a90ed27b 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosError, AxiosInstance } from 'axios'; import { Agent as HttpsAgent } from 'https'; import HttpProxyAgent from 'http-proxy-agent'; import { HttpsProxyAgent } from 'https-proxy-agent'; @@ -21,6 +21,7 @@ import { import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '../actions_config.mock'; import { getCustomAgents } from './get_custom_agents'; +import { ConnectorUsageCollector } from '../usage/connector_usage_collector'; const TestUrl = 'https://elastic.co/foo/bar/baz'; @@ -79,6 +80,80 @@ describe('request', () => { }); }); + test('adds request body bytes from request header on a successful request when connectorUsageCollector is provided', async () => { + const contentLength = 12; + axiosMock.mockImplementation(() => ({ + status: 200, + headers: { 'content-type': 'application/json' }, + data: { incidentId: '123' }, + request: { + headers: { 'Content-Length': contentLength }, + getHeader: () => contentLength, + }, + })); + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + await request({ + axios, + url: '/test', + logger, + data: { test: 12345 }, + configurationUtilities, + connectorUsageCollector, + }); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + }); + + test('adds request body bytes from request header on a failed', async () => { + const contentLength = 12; + axiosMock.mockImplementation( + () => + new AxiosError('failed', '500', undefined, { + headers: { 'Content-Length': contentLength }, + }) + ); + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + + try { + await request({ + axios, + url: '/test', + logger, + configurationUtilities, + connectorUsageCollector, + }); + } catch (e) { + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + } + }); + + test('adds request body bytes from data when request header does not exist', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 12345 }; + + await request({ + axios, + url: '/test', + logger, + data, + configurationUtilities, + connectorUsageCollector, + }); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe( + Buffer.byteLength(JSON.stringify(data), 'utf8') + ); + }); + test('it have been called with proper proxy agent for a valid url', async () => { configurationUtilities.getProxySettings.mockReturnValue({ proxySSLSettings: { diff --git a/x-pack/plugins/actions/server/lib/axios_utils.ts b/x-pack/plugins/actions/server/lib/axios_utils.ts index 3852f2a33755b..254ad1a36f6e2 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.ts @@ -17,7 +17,7 @@ import { import { Logger } from '@kbn/core/server'; import { getCustomAgents } from './get_custom_agents'; import { ActionsConfigurationUtilities } from '../actions_config'; -import { SSLSettings } from '../types'; +import { ConnectorUsageCollector, SSLSettings } from '../types'; import { combineHeadersWithBasicAuthHeader } from './get_basic_auth_header'; export const request = async ({ @@ -30,6 +30,7 @@ export const request = async ({ headers, sslOverrides, timeout, + connectorUsageCollector, ...config }: { axios: AxiosInstance; @@ -41,6 +42,7 @@ export const request = async ({ headers?: Record; timeout?: number; sslOverrides?: SSLSettings; + connectorUsageCollector?: ConnectorUsageCollector; } & AxiosRequestConfig): Promise => { if (!isEmpty(axios?.defaults?.baseURL ?? '')) { throw new Error( @@ -64,18 +66,31 @@ export const request = async ({ headers, }); - return await axios(url, { - ...restConfig, - method, - headers: headersWithBasicAuth, - ...(data ? { data } : {}), - // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs - httpAgent, - httpsAgent, - proxy: false, - maxContentLength, - timeout: Math.max(settingsTimeout, timeout ?? 0), - }); + try { + const result = await axios(url, { + ...restConfig, + method, + headers: headersWithBasicAuth, + ...(data ? { data } : {}), + // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs + httpAgent, + httpsAgent, + proxy: false, + maxContentLength, + timeout: Math.max(settingsTimeout, timeout ?? 0), + }); + + if (connectorUsageCollector) { + connectorUsageCollector.addRequestBodyBytes(result, data); + } + + return result; + } catch (error) { + if (connectorUsageCollector) { + connectorUsageCollector.addRequestBodyBytes(error, data); + } + throw error; + } }; export const patch = async ({ @@ -84,12 +99,14 @@ export const patch = async ({ data, logger, configurationUtilities, + connectorUsageCollector, }: { axios: AxiosInstance; url: string; data: T; logger: Logger; configurationUtilities: ActionsConfigurationUtilities; + connectorUsageCollector?: ConnectorUsageCollector; }): Promise => { return request({ axios, @@ -98,6 +115,7 @@ export const patch = async ({ method: 'patch', data, configurationUtilities, + connectorUsageCollector, }); }; diff --git a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts index cb6390a4b3335..46f13ae1182ac 100644 --- a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts +++ b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts @@ -33,6 +33,7 @@ describe('createActionEventLogRecordObject', () => { spaceId: 'default', name: 'test name', actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ '@timestamp': '1970-01-01T00:00:00.000Z', @@ -64,6 +65,7 @@ describe('createActionEventLogRecordObject', () => { }, action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -92,6 +94,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -118,6 +121,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -145,6 +149,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -163,6 +168,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -192,6 +198,7 @@ describe('createActionEventLogRecordObject', () => { ], name: 'test name', actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -220,6 +227,7 @@ describe('createActionEventLogRecordObject', () => { }, action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -255,6 +263,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -289,6 +298,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -319,6 +329,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', source: asHttpRequestExecutionSource(httpServerMock.createKibanaRequest()), + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -345,6 +356,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { source: 'http_request', @@ -376,6 +388,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', source: asHttpRequestExecutionSource(httpServerMock.createKibanaRequest()), + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -402,6 +415,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { source: 'http_request', @@ -433,6 +447,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', isInMemory: true, + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -460,6 +475,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', diff --git a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts index 4f8bf08966c59..c3b7a3b35f512 100644 --- a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts +++ b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts @@ -37,6 +37,7 @@ interface CreateActionEventLogRecordParams { relatedSavedObjects?: RelatedSavedObjects; isInMemory?: boolean; source?: ActionExecutionSource; + actionTypeId: string; } export function createActionEventLogRecordObject(params: CreateActionEventLogRecordParams): Event { @@ -54,6 +55,7 @@ export function createActionEventLogRecordObject(params: CreateActionEventLogRec isInMemory, actionId, source, + actionTypeId, } = params; const kibanaAlertRule = { @@ -89,6 +91,7 @@ export function createActionEventLogRecordObject(params: CreateActionEventLogRec action: { ...(name ? { name } : {}), id: actionId, + type_id: actionTypeId, execution: { uuid: actionExecutionId, }, diff --git a/x-pack/plugins/actions/server/sub_action_framework/case.test.ts b/x-pack/plugins/actions/server/sub_action_framework/case.test.ts index 91e2df1972de8..aa32dd8853dba 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/case.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/case.test.ts @@ -12,12 +12,14 @@ import { actionsConfigMock } from '../actions_config.mock'; import { actionsMock } from '../mocks'; import { TestCaseConnector } from './mocks'; import { ActionsConfigurationUtilities } from '../actions_config'; +import { ConnectorUsageCollector } from '../usage'; describe('CaseConnector', () => { let logger: MockedLogger; let services: ReturnType; let mockedActionsConfig: jest.Mocked; let service: TestCaseConnector; + let connectorUsageCollector: ConnectorUsageCollector; const pushToServiceIncidentParamsSchema = { name: schema.string(), category: schema.nullable(schema.string()), @@ -57,6 +59,11 @@ describe('CaseConnector', () => { }, pushToServiceIncidentParamsSchema ); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('Sub actions', () => { @@ -191,7 +198,7 @@ describe('CaseConnector', () => { describe('pushToService', () => { it('should create an incident if externalId is null', async () => { - const res = await service.pushToService(pushToServiceParams); + const res = await service.pushToService(pushToServiceParams, connectorUsageCollector); expect(res).toEqual({ id: 'create-incident', title: 'Test incident', @@ -201,10 +208,13 @@ describe('CaseConnector', () => { }); it('should update an incident if externalId is not null', async () => { - const res = await service.pushToService({ - incident: { ...pushToServiceParams.incident, externalId: 'test-id' }, - comments: [], - }); + const res = await service.pushToService( + { + incident: { ...pushToServiceParams.incident, externalId: 'test-id' }, + comments: [], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'update-incident', @@ -215,13 +225,16 @@ describe('CaseConnector', () => { }); it('should add comments', async () => { - const res = await service.pushToService({ - ...pushToServiceParams, - comments: [ - { comment: 'comment-1', commentId: 'comment-id-1' }, - { comment: 'comment-2', commentId: 'comment-id-2' }, - ], - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + comments: [ + { comment: 'comment-1', commentId: 'comment-id-1' }, + { comment: 'comment-2', commentId: 'comment-id-2' }, + ], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', @@ -242,11 +255,14 @@ describe('CaseConnector', () => { }); it.each([[undefined], [null]])('should throw if externalId is %p', async (comments) => { - const res = await service.pushToService({ - ...pushToServiceParams, - // @ts-expect-error - comments, - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + // @ts-expect-error + comments, + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', @@ -257,10 +273,13 @@ describe('CaseConnector', () => { }); it('should not add comments if comments are an empty array', async () => { - const res = await service.pushToService({ - ...pushToServiceParams, - comments: [], - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + comments: [], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', diff --git a/x-pack/plugins/actions/server/sub_action_framework/case.ts b/x-pack/plugins/actions/server/sub_action_framework/case.ts index 24a0512378912..1d942b210dbf9 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/case.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/case.ts @@ -9,22 +9,38 @@ import { schema, Type } from '@kbn/config-schema'; import { ExternalServiceIncidentResponse, PushToServiceResponse } from './types'; import { SubActionConnector } from './sub_action_connector'; import { ServiceParams } from './types'; +import { ConnectorUsageCollector } from '../usage'; export interface CaseConnectorInterface { - addComment: ({ incidentId, comment }: { incidentId: string; comment: string }) => Promise; - createIncident: (incident: Incident) => Promise; - updateIncident: ({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }) => Promise; - getIncident: ({ id }: { id: string }) => Promise; - pushToService: (params: { - incident: { externalId: string | null } & Incident; - comments: Array<{ commentId: string; comment: string }>; - }) => Promise; + addComment: ( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + createIncident: ( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + updateIncident: ( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + getIncident: ( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + pushToService: ( + params: { + incident: { externalId: string | null } & Incident; + comments: Array<{ commentId: string; comment: string }>; + }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; } export abstract class CaseConnector @@ -56,50 +72,71 @@ export abstract class CaseConnector; + public abstract addComment( + { + incidentId, + comment, + }: { + incidentId: string; + comment: string; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; - public abstract createIncident(incident: Incident): Promise; - public abstract updateIncident({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }): Promise; - public abstract getIncident({ id }: { id: string }): Promise; + public abstract createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; + public abstract updateIncident( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; + public abstract getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; - public async pushToService(params: { - incident: { externalId: string | null } & Incident; - comments: Array<{ commentId: string; comment: string }>; - }) { + public async pushToService( + params: { + incident: { externalId: string | null } & Incident; + comments: Array<{ commentId: string; comment: string }>; + }, + connectorUsageCollector: ConnectorUsageCollector + ) { const { incident, comments } = params; const { externalId, ...rest } = incident; let res: PushToServiceResponse; if (externalId != null) { - res = await this.updateIncident({ - incidentId: externalId, - incident: rest as Incident, - }); + res = await this.updateIncident( + { + incidentId: externalId, + incident: rest as Incident, + }, + connectorUsageCollector + ); } else { - res = await this.createIncident(rest as Incident); + res = await this.createIncident(rest as Incident, connectorUsageCollector); } if (comments && Array.isArray(comments) && comments.length > 0) { res.comments = []; for (const currentComment of comments) { - await this.addComment({ - incidentId: res.id, - comment: currentComment.comment, - }); + await this.addComment( + { + incidentId: res.id, + comment: currentComment.comment, + }, + connectorUsageCollector + ); res.comments = [ ...(res.comments ?? []), diff --git a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts index 35b1fa43c6ce3..1b8bdf0adcaee 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts @@ -21,6 +21,7 @@ import { } from './mocks'; import { IService, ServiceParams } from './types'; import { getErrorSource, TaskErrorSource } from '@kbn/task-manager-plugin/server/task_running'; +import { ConnectorUsageCollector } from '../usage'; describe('Executor', () => { const actionId = 'test-action-id'; @@ -30,6 +31,7 @@ describe('Executor', () => { let logger: MockedLogger; let services: ReturnType; let mockedActionsConfig: jest.Mocked; + let connectorUsageCollector: ConnectorUsageCollector; const createExecutor = (Service: IService) => { const connector = { @@ -55,6 +57,10 @@ describe('Executor', () => { logger = loggingSystemMock.createLogger(); services = actionsMock.createServices(); mockedActionsConfig = actionsConfigMock.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('should execute correctly', async () => { @@ -68,6 +74,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -90,6 +97,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -112,6 +120,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -132,6 +141,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -153,6 +163,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError('You should register at least one subAction for your connector type'); }); @@ -169,6 +180,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Sub action "not-exist" is not registered. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -187,6 +199,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); } catch (e) { expect(getErrorSource(e)).toBe(TaskErrorSource.USER); @@ -208,6 +221,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Method "not-exist" does not exists in service. Sub action: "testUrl". Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -226,6 +240,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Method "notAFunction" must be a function. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -244,9 +259,50 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Request validation failed (Error: [id]: expected value of type [string] but got [undefined])' ); }); + + it('Passes connectorUsageCollector to the subAction method as a second param', async () => { + let echoSpy; + + const subActionParams = { id: 'test-id' }; + const connector = { + id: '.test', + name: 'Test', + minimumLicenseRequired: 'basic' as const, + supportedFeatureIds: ['alerting'], + schema: { + config: TestConfigSchema, + secrets: TestSecretsSchema, + }, + getService: (serviceParams: ServiceParams) => { + const service = new TestExecutor(serviceParams); + echoSpy = jest.spyOn(service, 'echo').mockResolvedValue(subActionParams); + return service; + }, + }; + + const executor = buildExecutor({ + configurationUtilities: mockedActionsConfig, + logger, + connector, + }); + + await executor({ + actionId, + params: { subAction: 'echo', subActionParams }, + config, + secrets, + services, + configurationUtilities: mockedActionsConfig, + logger, + connectorUsageCollector, + }); + + expect(echoSpy).toHaveBeenCalledWith(subActionParams, connectorUsageCollector); + }); }); diff --git a/x-pack/plugins/actions/server/sub_action_framework/executor.ts b/x-pack/plugins/actions/server/sub_action_framework/executor.ts index d9f2f693c175d..a8fbcb6e05984 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/executor.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/executor.ts @@ -30,7 +30,15 @@ export const buildExecutor = < logger: Logger; configurationUtilities: ActionsConfigurationUtilities; }): ExecutorType => { - return async ({ actionId, params, config, secrets, services, request }) => { + return async ({ + actionId, + params, + config, + secrets, + services, + request, + connectorUsageCollector, + }) => { const subAction = params.subAction; const subActionParams = params.subActionParams; @@ -88,7 +96,7 @@ export const buildExecutor = < } } - const data = await func.call(service, subActionParams); + const data = await func.call(service, subActionParams, connectorUsageCollector); return { status: 'ok', data: data ?? {}, actionId }; }; }; diff --git a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts index f6c8e86dd5af3..28e4a2abc224e 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts @@ -8,6 +8,7 @@ import { schema, Type, TypeOf } from '@kbn/config-schema'; import { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '../usage'; import { SubActionConnector } from './sub_action_connector'; import { CaseConnector } from './case'; import { ExternalServiceIncidentResponse, ServiceParams } from './types'; @@ -57,36 +58,54 @@ export class TestSubActionConnector extends SubActionConnector | null }) { - const res = await this.request({ - url, - data, - headers: { 'X-Test-Header': 'test' }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testUrl( + { url, data = {} }: { url: string; data?: Record | null }, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url, + data, + headers: { 'X-Test-Header': 'test' }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } - public async testData({ data }: { data: Record }) { - const res = await this.request({ - url: 'https://example.com', - data: this.removeNullOrUndefinedFields(data), - headers: { 'X-Test-Header': 'test' }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testData( + { data }: { data: Record }, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url: 'https://example.com', + data: this.removeNullOrUndefinedFields(data), + headers: { 'X-Test-Header': 'test' }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } - public async testAuth({ headers }: { headers?: Record } = {}) { - const res = await this.request({ - url: 'https://example.com', - data: {}, - auth: { username: 'username', password: 'password' }, - headers: { 'X-Test-Header': 'test', ...headers }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testAuth( + { headers }: { headers?: Record } = {}, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url: 'https://example.com', + data: {}, + auth: { username: 'username', password: 'password' }, + headers: { 'X-Test-Header': 'test', ...headers }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts index 1358684d86093..ed599c3f30f71 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts @@ -13,6 +13,7 @@ import { actionsMock } from '../mocks'; import { TestSubActionConnector } from './mocks'; import { ActionsConfigurationUtilities } from '../actions_config'; import * as utils from '../lib/axios_utils'; +import { ConnectorUsageCollector } from '../usage'; jest.mock('axios'); @@ -43,6 +44,7 @@ describe('SubActionConnector', () => { let services: ReturnType; let mockedActionsConfig: jest.Mocked; let service: TestSubActionConnector; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.resetAllMocks(); @@ -70,6 +72,11 @@ describe('SubActionConnector', () => { secrets: { username: 'elastic', password: 'changeme' }, services, }); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('Sub actions', () => { @@ -85,34 +92,37 @@ describe('SubActionConnector', () => { describe('URL validation', () => { it('removes double slashes correctly', async () => { - await service.testUrl({ url: 'https://example.com//api///test-endpoint' }); + await service.testUrl( + { url: 'https://example.com//api///test-endpoint' }, + connectorUsageCollector + ); expect(requestMock.mock.calls[0][0].url).toBe('https://example.com/api/test-endpoint'); }); it('removes the ending slash correctly', async () => { - await service.testUrl({ url: 'https://example.com/' }); + await service.testUrl({ url: 'https://example.com/' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0].url).toBe('https://example.com'); }); it('throws an error if the url is invalid', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: 'invalid-url' })).rejects.toThrow( - 'URL Error: Invalid URL: invalid-url' - ); + await expect(async () => + service.testUrl({ url: 'invalid-url' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid URL: invalid-url'); }); it('throws an error if the url starts with backslashes', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: '//example.com/foo' })).rejects.toThrow( - 'URL Error: Invalid URL: //example.com/foo' - ); + await expect(async () => + service.testUrl({ url: '//example.com/foo' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid URL: //example.com/foo'); }); it('throws an error if the protocol is not supported', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: 'ftp://example.com' })).rejects.toThrow( - 'URL Error: Invalid protocol' - ); + await expect(async () => + service.testUrl({ url: 'ftp://example.com' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid protocol'); }); it('throws if the host is the URI is not allowed', async () => { @@ -122,15 +132,15 @@ describe('SubActionConnector', () => { throw new Error('URI is not allowed'); }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( - 'error configuring connector action: URI is not allowed' - ); + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow('error configuring connector action: URI is not allowed'); }); }); describe('Data', () => { it('sets data to an empty object if the data are null', async () => { - await service.testUrl({ url: 'https://example.com', data: null }); + await service.testUrl({ url: 'https://example.com', data: null }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -138,7 +148,10 @@ describe('SubActionConnector', () => { }); it('pass data to axios correctly if not null', async () => { - await service.testUrl({ url: 'https://example.com', data: { foo: 'foo' } }); + await service.testUrl( + { url: 'https://example.com', data: { foo: 'foo' } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -146,7 +159,10 @@ describe('SubActionConnector', () => { }); it('removeNullOrUndefinedFields: removes null values and undefined values correctly', async () => { - await service.testData({ data: { foo: 'foo', bar: null, baz: undefined } }); + await service.testData( + { data: { foo: 'foo', bar: null, baz: undefined } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -167,7 +183,7 @@ describe('SubActionConnector', () => { describe('Fetching', () => { it('fetch correctly', async () => { - const res = await service.testUrl({ url: 'https://example.com' }); + const res = await service.testUrl({ url: 'https://example.com' }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -181,6 +197,7 @@ describe('SubActionConnector', () => { 'X-Test-Header': 'test', }, url: 'https://example.com', + connectorUsageCollector, }); expect(logger.debug).toBeCalledWith( @@ -192,7 +209,9 @@ describe('SubActionConnector', () => { it('validates the response correctly', async () => { requestMock.mockReturnValue({ data: { invalidField: 'test' } }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow( 'Response validation failed (Error: [status]: expected value of type [string] but got [undefined])' ); }); @@ -202,9 +221,9 @@ describe('SubActionConnector', () => { throw createAxiosError(); }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( - 'Message: An error occurred. Code: 500' - ); + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow('Message: An error occurred. Code: 500'); expect(logger.debug).toHaveBeenLastCalledWith( 'Request to external service failed. Connector Id: test-id. Connector type: .test. Method: get. URL: https://example.com' @@ -212,7 +231,7 @@ describe('SubActionConnector', () => { }); it('converts auth axios property to a basic auth header if provided', async () => { - await service.testAuth(); + await service.testAuth(undefined, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -227,11 +246,15 @@ describe('SubActionConnector', () => { Authorization: `Basic ${Buffer.from('username:password').toString('base64')}`, }, url: 'https://example.com', + connectorUsageCollector, }); }); it('does not override an authorization header if provided', async () => { - await service.testAuth({ headers: { Authorization: 'Bearer my_token' } }); + await service.testAuth( + { headers: { Authorization: 'Bearer my_token' } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -246,6 +269,7 @@ describe('SubActionConnector', () => { Authorization: 'Bearer my_token', }, url: 'https://example.com', + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts index d5ad5391628bc..fe59feab4376b 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts @@ -24,6 +24,7 @@ import { IncomingMessage } from 'http'; import { PassThrough } from 'stream'; import { KibanaRequest } from '@kbn/core-http-server'; import { inspect } from 'util'; +import { ConnectorUsageCollector } from '../usage'; import { assertURL } from './helpers/validators'; import { ActionsConfigurationUtilities } from '../actions_config'; import { SubAction, SubActionRequestParams } from './types'; @@ -130,15 +131,18 @@ export abstract class SubActionConnector { protected abstract getResponseErrorMessage(error: AxiosError): string; - protected async request({ - url, - data, - method = 'get', - responseSchema, - headers, - timeout, - ...config - }: SubActionRequestParams): Promise> { + protected async request( + { + url, + data, + method = 'get', + responseSchema, + headers, + timeout, + ...config + }: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise> { try { this.assertURL(url); this.ensureUriAllowed(url); @@ -160,6 +164,7 @@ export abstract class SubActionConnector { configurationUtilities: this.configurationUtilities, headers: this.getHeaders(auth, headers as AxiosHeaders), timeout, + connectorUsageCollector, }); this.validateResponse(responseSchema, res.data); diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index aa6c7b26cf0ae..487e7630d40f9 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -39,11 +39,11 @@ export type ActionTypeSecrets = Record; export type ActionTypeParams = Record; export type ConnectorTokenClientContract = PublicMethodsOf; -import type { ActionExecutionSource } from './lib'; import { Connector, ConnectorWithExtraFindData } from './application/connector/types'; -export type { ActionExecutionSource } from './lib'; - +import type { ActionExecutionSource } from './lib'; export { ActionExecutionSourceType } from './lib'; +import { ConnectorUsageCollector } from './usage'; +export { ConnectorUsageCollector } from './usage'; export interface Services { savedObjectsClient: SavedObjectsClientContract; @@ -88,6 +88,7 @@ export interface ActionTypeExecutorOptions< configurationUtilities: ActionsConfigurationUtilities; source?: ActionExecutionSource; request?: KibanaRequest; + connectorUsageCollector: ConnectorUsageCollector; } export type ActionResult = Connector; diff --git a/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts b/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts index 8331f6890486c..066c477947e2c 100644 --- a/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts +++ b/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts @@ -12,11 +12,8 @@ import { ExecuteOptions, ExecutionResponse, } from '../create_unsecured_execute_function'; -import { - ActionExecutorContract, - asNotificationExecutionSource, - type RelatedSavedObjects, -} from '../lib'; +import { ActionExecutorContract, asNotificationExecutionSource } from '../lib'; +import type { RelatedSavedObjects } from '../lib'; import { ActionTypeExecutorResult, InMemoryConnector } from '../types'; import { asBackgroundTaskExecutionSource } from '../lib/action_execution_source'; import { ConnectorWithExtraFindData } from '../application/connector/types'; diff --git a/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts b/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts new file mode 100644 index 0000000000000..dcf071685f24f --- /dev/null +++ b/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts @@ -0,0 +1,102 @@ +/* + * 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 { ConnectorUsageCollector } from '../types'; +import { AxiosHeaders, AxiosResponse } from 'axios'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; + +describe('ConnectorUsageCollector', () => { + const logger = loggingSystemMock.createLogger(); + + test('it collects requestBodyBytes from response.request.headers', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 'foo' }; + const contentLength = Buffer.byteLength(JSON.stringify(data), 'utf8'); + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + headers: { 'Content-Length': contentLength }, + getHeader: () => contentLength, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength + contentLength); + }); + test('it collects requestBodyBytes from data when header is is missing', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 'foo' }; + const contentLength = Buffer.byteLength(JSON.stringify(data), 'utf8'); + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + getHeader: () => undefined, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength + contentLength); + }); + + test('it logs an error when the body cannot be stringified ', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + + const data = { + name: 'arun', + }; + + // @ts-ignore + data.foo = data; // this is to force JSON.stringify to throw + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + getHeader: () => undefined, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(logger.error).toHaveBeenCalledTimes(1); + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining("Request body bytes couldn't be calculated, Error: ") + ); + }); +}); diff --git a/x-pack/plugins/actions/server/usage/connector_usage_collector.ts b/x-pack/plugins/actions/server/usage/connector_usage_collector.ts new file mode 100644 index 0000000000000..542be0ebf7c70 --- /dev/null +++ b/x-pack/plugins/actions/server/usage/connector_usage_collector.ts @@ -0,0 +1,52 @@ +/* + * 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 { AxiosError, AxiosResponse } from 'axios'; +import { Logger } from '@kbn/core/server'; +import { isUndefined } from 'lodash'; + +interface ConnectorUsage { + requestBodyBytes: number; +} + +export class ConnectorUsageCollector { + private connectorId: string; + private usage: ConnectorUsage = { + requestBodyBytes: 0, + }; + + private logger: Logger; + + constructor({ logger, connectorId }: { logger: Logger; connectorId: string }) { + this.logger = logger; + this.connectorId = connectorId; + } + + public addRequestBodyBytes(result?: AxiosError | AxiosResponse, body: string | object = '') { + const contentLength = result?.request?.getHeader('content-length'); + let bytes = 0; + + if (!isUndefined(contentLength)) { + bytes = parseInt(contentLength, 10); + } else { + try { + const sBody = typeof body === 'string' ? body : JSON.stringify(body); + bytes = Buffer.byteLength(sBody, 'utf8'); + } catch (e) { + this.logger.error( + `Request body bytes couldn't be calculated, Error: ${e.message}, connectorId:${this.connectorId}` + ); + } + } + + this.usage.requestBodyBytes = this.usage.requestBodyBytes + bytes; + } + + public getRequestBodyByte() { + return this.usage.requestBodyBytes; + } +} diff --git a/x-pack/plugins/actions/server/usage/index.ts b/x-pack/plugins/actions/server/usage/index.ts index 722ad76014f07..d4faf364b7295 100644 --- a/x-pack/plugins/actions/server/usage/index.ts +++ b/x-pack/plugins/actions/server/usage/index.ts @@ -6,3 +6,4 @@ */ export { registerActionsUsageCollector } from './actions_usage_collector'; +export { ConnectorUsageCollector } from './connector_usage_collector'; diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index 98908f516fc96..5fc8128baa7ae 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -482,6 +482,10 @@ "type": "keyword", "ignore_above": 1024 }, + "type_id": { + "type": "keyword", + "ignore_above": 1024 + }, "execution": { "properties": { "source": { @@ -508,6 +512,13 @@ } } } + }, + "usage": { + "properties": { + "request_body_bytes": { + "type": "long" + } + } } } } diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index f8db21105539e..7542d6db5213a 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -212,6 +212,7 @@ export const EventSchema = schema.maybe( schema.object({ name: ecsString(), id: ecsString(), + type_id: ecsString(), execution: schema.maybe( schema.object({ source: ecsString(), @@ -227,6 +228,11 @@ export const EventSchema = schema.maybe( ), }) ), + usage: schema.maybe( + schema.object({ + request_body_bytes: ecsStringOrNumber(), + }) + ), }) ), }) diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index aa91f7fc5c2d6..770f9e6d45f9a 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -257,6 +257,10 @@ exports.EcsCustomPropertyMappings = { type: 'keyword', ignore_above: 1024, }, + type_id: { + type: 'keyword', + ignore_above: 1024, + }, execution: { properties: { source: { @@ -284,6 +288,13 @@ exports.EcsCustomPropertyMappings = { }, }, }, + usage: { + properties: { + request_body_bytes: { + type: 'long', + }, + }, + }, }, }, }, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts index ce85e27a8eb43..2a4d91a07f1d3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts @@ -25,6 +25,7 @@ import { import { DEFAULT_BODY } from '../../../public/connector_types/bedrock/constants'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); // @ts-ignore @@ -37,6 +38,7 @@ describe('BedrockConnector', () => { completion: mockResponseString, stop_reason: 'stop_sequence', }; + const logger = loggingSystemMock.createLogger(); const claude3Response = { id: 'compl_01E7D3vTBHdNdKWCe6zALmLH', @@ -57,12 +59,18 @@ describe('BedrockConnector', () => { headers: {}, data: claude3Response, }; + let connectorUsageCollector: ConnectorUsageCollector; + beforeEach(() => { jest.clearAllMocks(); mockRequest = jest.fn().mockResolvedValue(mockResponse); mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); const connector = new BedrockConnector({ @@ -73,7 +81,7 @@ describe('BedrockConnector', () => { defaultModel: DEFAULT_BEDROCK_MODEL, }, secrets: { accessKey: '123', secret: 'secret' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); @@ -85,7 +93,13 @@ describe('BedrockConnector', () => { describe('runApi', () => { it('the aws signature has non-streaming headers', async () => { - await connector.runApi({ body: DEFAULT_BODY }); + await connector.runApi( + { body: DEFAULT_BODY }, + new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }) + ); expect(mockSigner).toHaveBeenCalledWith( { body: DEFAULT_BODY, @@ -101,16 +115,19 @@ describe('BedrockConnector', () => { ); }); it('the Bedrock API call is successful with Claude 3 parameters; returns the response formatted for Claude 2 along with usage object', async () => { - const response = await connector.runApi({ body: DEFAULT_BODY }); + const response = await connector.runApi({ body: DEFAULT_BODY }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: DEFAULT_BODY, - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: DEFAULT_BODY, + }, + connectorUsageCollector + ); expect(response).toEqual({ ...claude2Response, usage: claude3Response.usage, @@ -128,16 +145,19 @@ describe('BedrockConnector', () => { }); // @ts-ignore connector.request = mockRequest; - const response = await connector.runApi({ body: v2Body }); + const response = await connector.runApi({ body: v2Body }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunActionResponseSchema, - data: v2Body, - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunActionResponseSchema, + data: v2Body, + }, + connectorUsageCollector + ); expect(response).toEqual(claude2Response); }); @@ -145,7 +165,15 @@ describe('BedrockConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: DEFAULT_BODY })).rejects.toThrow('API Error'); + await expect( + connector.runApi( + { body: DEFAULT_BODY }, + new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }) + ) + ).rejects.toThrow('API Error'); }); }); @@ -170,7 +198,7 @@ describe('BedrockConnector', () => { }; it('the aws signature has streaming headers', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockSigner).toHaveBeenCalledWith( { @@ -189,170 +217,197 @@ describe('BedrockConnector', () => { }); it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), + }, + connectorUsageCollector + ); }); it('signal and timeout is properly passed to streamApi', async () => { const signal = jest.fn(); const timeout = 180000; - await connector.invokeStream({ ...aiAssistantBody, timeout, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), - timeout, - signal, - }); + await connector.invokeStream( + { ...aiAssistantBody, timeout, signal }, + connectorUsageCollector + ); + + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), + timeout, + signal, + }, + connectorUsageCollector + ); }); it('ensureMessageFormat - formats messages from user, assistant, and system', async () => { - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + await connector.invokeStream( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('ensureMessageFormat - formats messages from when double user/assistant occurs', async () => { - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'assistant', - content: 'But I can be naughty', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - { - role: 'user', - content: 'I can be naughty too', - }, - { - role: 'system', - content: 'This is extra tricky', - }, - ], - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot\nThis is extra tricky', + await connector.invokeStream( + { messages: [ - { content: 'Hi, I am a good chatbot\nBut I can be naughty', role: 'assistant' }, - { content: 'What is 2+2?\nI can be naughty too', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'assistant', + content: 'But I can be naughty', + }, + { + role: 'user', + content: 'What is 2+2?', + }, + { + role: 'user', + content: 'I can be naughty too', + }, + { + role: 'system', + content: 'This is extra tricky', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot\nThis is extra tricky', + messages: [ + { content: 'Hi, I am a good chatbot\nBut I can be naughty', role: 'assistant' }, + { content: 'What is 2+2?\nI can be naughty too', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('formats the system message as a user message for claude<2.1', async () => { const modelOverride = 'anthropic.claude-v2'; - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - model: modelOverride, - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${modelOverride}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + await connector.invokeStream( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + model: modelOverride, + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${modelOverride}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('responds with a readable stream', async () => { - const response = await connector.invokeStream(aiAssistantBody); + const response = await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(response instanceof PassThrough).toEqual(true); }); @@ -360,7 +415,9 @@ describe('BedrockConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeStream(aiAssistantBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeStream(aiAssistantBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -376,175 +433,201 @@ describe('BedrockConnector', () => { }; it('the API call is successful with correct parameters', async () => { - const response = await connector.invokeAI(aiAssistantBody); + const response = await connector.invokeAI(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - ...JSON.parse(DEFAULT_BODY), - messages: [{ content: 'Hello world', role: 'user' }], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + ...JSON.parse(DEFAULT_BODY), + messages: [{ content: 'Hello world', role: 'user' }], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('formats messages from user, assistant, and system', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('adds system message from argument', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - system: 'This is a system message', - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'This is a system message', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + system: 'This is a system message', + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'This is a system message', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('combines argument system message with conversation system message', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - system: 'This is a system message', - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'This is a system message\nBe a good chatbot', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + system: 'This is a system message', + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'This is a system message\nBe a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('signal and timeout is properly passed to runApi', async () => { const signal = jest.fn(); const timeout = 180000; - await connector.invokeAI({ ...aiAssistantBody, timeout, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - ...JSON.parse(DEFAULT_BODY), - messages: [{ content: 'Hello world', role: 'user' }], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - timeout, - signal, - }); + await connector.invokeAI({ ...aiAssistantBody, timeout, signal }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + ...JSON.parse(DEFAULT_BODY), + messages: [{ content: 'Hello world', role: 'user' }], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + timeout, + signal, + }, + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeAI(aiAssistantBody)).rejects.toThrow('API Error'); + await expect(connector.invokeAI(aiAssistantBody, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); describe('getResponseErrorMessage', () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts index 6b981a365b63a..b5ec114a9c456 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts @@ -11,6 +11,7 @@ import { AxiosError, Method } from 'axios'; import { IncomingMessage } from 'http'; import { PassThrough } from 'stream'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { RunActionParamsSchema, @@ -194,16 +195,18 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B } private async runApiRaw( - params: SubActionRequestParams + params: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request(params); + const response = await this.request(params, connectorUsageCollector); return response.data; } private async runApiLatest( - params: SubActionRequestParams + params: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request(params); + const response = await this.request(params, connectorUsageCollector); // keeping the response the same as claude 2 for our APIs // adding the usage object for better token tracking return { @@ -218,13 +221,10 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async runApi({ - body, - model: reqModel, - signal, - timeout, - raw, - }: RunActionParams): Promise { + public async runApi( + { body, model: reqModel, signal, timeout, raw }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const currentModel = reqModel ?? this.model; const path = `/model/${currentModel}/invoke`; @@ -240,13 +240,22 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B }; if (raw) { - return this.runApiRaw({ ...requestArgs, responseSchema: InvokeAIRawActionResponseSchema }); + return this.runApiRaw( + { ...requestArgs, responseSchema: InvokeAIRawActionResponseSchema }, + connectorUsageCollector + ); } // possible api received deprecated arguments, which will still work with the deprecated Claude 2 models if (usesDeprecatedArguments(body)) { - return this.runApiRaw({ ...requestArgs, responseSchema: RunActionResponseSchema }); + return this.runApiRaw( + { ...requestArgs, responseSchema: RunActionResponseSchema }, + connectorUsageCollector + ); } - return this.runApiLatest({ ...requestArgs, responseSchema: RunApiLatestResponseSchema }); + return this.runApiLatest( + { ...requestArgs, responseSchema: RunApiLatestResponseSchema }, + connectorUsageCollector + ); } /** @@ -257,26 +266,27 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - private async streamApi({ - body, - model: reqModel, - signal, - timeout, - }: RunActionParams): Promise { + private async streamApi( + { body, model: reqModel, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const path = `/model/${reqModel ?? this.model}/invoke-with-response-stream`; const signed = this.signRequest(body, path, true); - const response = await this.request({ - ...signed, - url: `${this.url}${path}`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: body, - responseType: 'stream', - signal, - timeout, - }); + const response = await this.request( + { + ...signed, + url: `${this.url}${path}`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: body, + responseType: 'stream', + signal, + timeout, + }, + connectorUsageCollector + ); return response.data.pipe(new PassThrough()); } @@ -289,24 +299,30 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param messages An array of messages to be sent to the API * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async invokeStream({ - messages, - model, - stopSequences, - system, - temperature, - signal, - timeout, - tools, - }: InvokeAIActionParams | InvokeAIRawActionParams): Promise { - const res = (await this.streamApi({ - body: JSON.stringify( - formatBedrockBody({ messages, stopSequences, system, temperature, tools }) - ), + public async invokeStream( + { + messages, model, + stopSequences, + system, + temperature, signal, timeout, - })) as unknown as IncomingMessage; + tools, + }: InvokeAIActionParams | InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = (await this.streamApi( + { + body: JSON.stringify( + formatBedrockBody({ messages, stopSequences, system, temperature, tools }) + ), + model, + signal, + timeout, + }, + connectorUsageCollector + )) as unknown as IncomingMessage; return res; } @@ -318,54 +334,66 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. * @returns an object with the response string as a property called message */ - public async invokeAI({ - messages, - model, - stopSequences, - system, - temperature, - maxTokens, - signal, - timeout, - }: InvokeAIActionParams): Promise { - const res = (await this.runApi({ - body: JSON.stringify( - formatBedrockBody({ messages, stopSequences, system, temperature, maxTokens }) - ), + public async invokeAI( + { + messages, model, + stopSequences, + system, + temperature, + maxTokens, signal, timeout, - })) as RunActionResponse; + }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = (await this.runApi( + { + body: JSON.stringify( + formatBedrockBody({ messages, stopSequences, system, temperature, maxTokens }) + ), + model, + signal, + timeout, + }, + connectorUsageCollector + )) as RunActionResponse; return { message: res.completion.trim() }; } - public async invokeAIRaw({ - messages, - model, - stopSequences, - system, - temperature, - maxTokens = DEFAULT_TOKEN_LIMIT, - signal, - timeout, - tools, - anthropicVersion, - }: InvokeAIRawActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify({ - messages, - stop_sequences: stopSequences, - system, - temperature, - max_tokens: maxTokens, - tools, - anthropic_version: anthropicVersion, - }), + public async invokeAIRaw( + { + messages, model, + stopSequences, + system, + temperature, + maxTokens = DEFAULT_TOKEN_LIMIT, signal, timeout, - raw: true, - }); + tools, + anthropicVersion, + }: InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify({ + messages, + stop_sequences: stopSequences, + system, + temperature, + max_tokens: maxTokens, + tools, + anthropic_version: anthropicVersion, + }), + model, + signal, + timeout, + raw: true, + }, + connectorUsageCollector + ); return res; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts index 62dd881608605..ccd777634ec37 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts @@ -70,7 +70,7 @@ export async function executor( CasesWebhookActionParamsType > ): Promise> { - const { actionId, configurationUtilities, params, logger } = execOptions; + const { actionId, configurationUtilities, params, logger, connectorUsageCollector } = execOptions; const { subAction, subActionParams } = params; let data: CasesWebhookExecutorResultData | undefined; @@ -81,7 +81,8 @@ export async function executor( secrets: execOptions.secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts index 3a8cf2895e60e..a44b34bf88fce 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts @@ -14,6 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { AuthType, WebhookMethods, SSLCertType } from '../../../common/auth/constants'; import { CRT_FILE, KEY_FILE } from '../../../common/auth/mocks'; @@ -69,12 +70,17 @@ const sslConfig: CasesWebhookPublicConfigurationType = { hasAuth: true, }; const sslSecrets = { crt: CRT_FILE, key: KEY_FILE, password: 'foobar', user: null, pfx: null }; +let connectorUsageCollector: ConnectorUsageCollector; describe('Cases webhook service', () => { let service: ExternalService; let sslService: ExternalService; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( actionId, { @@ -82,7 +88,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); sslService = createExternalService( @@ -92,7 +99,8 @@ describe('Cases webhook service', () => { secrets: sslSecrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); jest.useFakeTimers(); jest.setSystemTime(mockTime); @@ -121,7 +129,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -135,7 +144,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: '', password: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -149,7 +159,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: '', password: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).not.toThrow(); }); @@ -162,7 +173,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -182,7 +194,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -225,6 +238,7 @@ describe('Cases webhook service', () => { logger, configurationUtilities, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -238,6 +252,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "logger": Object { "context": Array [], "debug": [MockFunction], @@ -481,6 +513,7 @@ describe('Cases webhook service', () => { configurationUtilities, sslOverrides: defaultSSLOverrides, data: `{"fields":{"title":"title","description":"desc","tags":["hello","world"],"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}`, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -510,6 +543,36 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"1234\\": [HTTP 200] OK", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", "logger": Object { "context": Array [], @@ -756,6 +819,7 @@ describe('Cases webhook service', () => { issuetype: { id: '10024' }, }, }), + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -776,6 +840,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", "logger": Object { "context": Array [], @@ -984,6 +1066,7 @@ describe('Cases webhook service', () => { sslOverrides: defaultSSLOverrides, url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment"}`, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -1004,6 +1087,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"body\\":\\"comment\\"}", "logger": Object { "context": Array [], @@ -1176,7 +1277,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); const res = await service.createComment(commentReq); expect(requestMock).not.toHaveBeenCalled(); @@ -1191,7 +1293,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); const res = await service.createComment(commentReq); expect(requestMock).not.toHaveBeenCalled(); @@ -1217,7 +1320,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); await service.createComment(commentReq); expect(requestMock).toHaveBeenCalledWith({ @@ -1228,6 +1332,7 @@ describe('Cases webhook service', () => { url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":"1"}`, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -1257,7 +1362,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); await service.createComment(commentReq2); expect(requestMock).toHaveBeenCalledWith({ @@ -1268,6 +1374,7 @@ describe('Cases webhook service', () => { url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":1}`, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); }); @@ -1286,7 +1393,8 @@ describe('Cases webhook service', () => { ensureUriAllowed: jest.fn().mockImplementation(() => { throw new Error('Uri not allowed'); }), - } + }, + connectorUsageCollector ); }); @@ -1360,7 +1468,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -1430,7 +1539,8 @@ describe('Cases webhook service', () => { logger, { ...configurationUtilities, - } + }, + connectorUsageCollector ); requestMock.mockImplementation(() => createAxiosResponse({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts index 424fe9b394517..170c63a1d4e5b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts @@ -12,6 +12,7 @@ import { renderMustacheStringNoEscape } from '@kbn/actions-plugin/server/lib/mus import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { buildConnectorAuth, validateConnectorAuthConfiguration } from '../../../common/auth/utils'; import { validateAndNormalizeUrl, validateJson } from './validators'; import { @@ -38,7 +39,8 @@ export const createExternalService = ( actionId: string, { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { createCommentJson, @@ -117,6 +119,7 @@ export const createExternalService = ( logger, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -162,6 +165,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); const { status, statusText, data } = res; @@ -246,6 +250,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -319,6 +324,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts index d53881cae1272..0c3d851981fde 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts @@ -10,27 +10,34 @@ import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.moc import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { CROWDSTRIKE_CONNECTOR_ID } from '../../../public/common'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const tokenPath = 'https://api.crowdstrike.com/oauth2/token'; const hostPath = 'https://api.crowdstrike.com/devices/entities/devices/v2'; const onlineStatusPath = 'https://api.crowdstrike.com/devices/entities/online-state/v1'; const actionsPath = 'https://api.crowdstrike.com/devices/entities/devices-actions/v2'; describe('CrowdstrikeConnector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new CrowdstrikeConnector({ configurationUtilities: actionsConfigMock.create(), connector: { id: '1', type: CROWDSTRIKE_CONNECTOR_ID }, config: { url: 'https://api.crowdstrike.com' }, secrets: { clientId: '123', clientSecret: 'secret' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); let mockedRequest: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { // @ts-expect-error private static - but I still want to reset it CrowdstrikeConnector.token = null; // @ts-expect-error mockedRequest = connector.request = jest.fn() as jest.Mock; + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); afterEach(() => { jest.clearAllMocks(); @@ -43,10 +50,13 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.executeHostActions({ - command: 'contain', - ids: ['id1', 'id2'], - }); + const result = await connector.executeHostActions( + { + command: 'contain', + ids: ['id1', 'id2'], + }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, expect.objectContaining({ @@ -58,7 +68,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -69,7 +80,8 @@ describe('CrowdstrikeConnector', () => { data: { ids: ['id1', 'id2'] }, paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), - }) + }), + connectorUsageCollector ); expect(result).toEqual({ id: 'testid', path: 'testpath' }); }); @@ -82,7 +94,10 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + const result = await connector.getAgentDetails( + { ids: ['id1', 'id2'] }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -95,7 +110,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -108,7 +124,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(result).toEqual({ resources: [{}] }); }); @@ -121,7 +138,10 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.getAgentOnlineStatus({ ids: ['id1', 'id2'] }); + const result = await connector.getAgentOnlineStatus( + { ids: ['id1', 'id2'] }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -134,7 +154,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -147,7 +168,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: onlineStatusPath, - }) + }), + connectorUsageCollector ); expect(result).toEqual({ resources: [{}] }); }); @@ -226,7 +248,7 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce(mockResponse); // @ts-expect-error private method - but I still want to - const result = await connector.getTokenRequest(); + const result = await connector.getTokenRequest(connectorUsageCollector); expect(mockedRequest).toHaveBeenCalledWith( expect.objectContaining({ @@ -237,7 +259,8 @@ describe('CrowdstrikeConnector', () => { 'Content-Type': 'application/x-www-form-urlencoded', authorization: expect.stringContaining('Basic'), }, - }) + }), + connectorUsageCollector ); expect(result).toEqual('testToken'); }); @@ -247,7 +270,7 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValue(mockResponse); - await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + await connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -260,7 +283,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -273,10 +297,11 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenCalledTimes(2); - await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + await connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector); expect(mockedRequest).toHaveBeenNthCalledWith( 3, expect.objectContaining({ @@ -288,7 +313,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenCalledTimes(3); }); @@ -298,9 +324,9 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockRejectedValueOnce(mockResponse); - await expect(() => connector.getAgentDetails({ ids: ['id1', 'id2'] })).rejects.toThrowError( - 'something goes wrong' - ); + await expect(() => + connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector) + ).rejects.toThrowError('something goes wrong'); expect(mockedRequest).toHaveBeenCalledTimes(2); }); it('should repeat the call one time if theres 401 error ', async () => { @@ -309,7 +335,9 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockRejectedValueOnce(mockResponse); - await expect(() => connector.getAgentDetails({ ids: ['id1', 'id2'] })).rejects.toThrowError(); + await expect(() => + connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector) + ).rejects.toThrowError(); expect(mockedRequest).toHaveBeenCalledTimes(3); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts index 3d14ae62924c4..a4fc84ae6a49a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts @@ -9,6 +9,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { isAggregateError, NodeSystemError } from './types'; import type { CrowdstrikeConfig, @@ -96,68 +97,87 @@ export class CrowdstrikeConnector extends SubActionConnector< }); } - public async executeHostActions({ alertIds, ...payload }: CrowdstrikeHostActionsParams) { - return this.crowdstrikeApiRequest({ - url: this.urls.hostAction, - method: 'post', - params: { - action_name: payload.command, - }, - data: { - ids: payload.ids, - ...(payload.actionParameters - ? { - action_parameters: Object.entries(payload.actionParameters).map(([name, value]) => ({ - name, - value, - })), - } - : {}), + public async executeHostActions( + { alertIds, ...payload }: CrowdstrikeHostActionsParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + return this.crowdstrikeApiRequest( + { + url: this.urls.hostAction, + method: 'post', + params: { + action_name: payload.command, + }, + data: { + ids: payload.ids, + ...(payload.actionParameters + ? { + action_parameters: Object.entries(payload.actionParameters).map( + ([name, value]) => ({ + name, + value, + }) + ), + } + : {}), + }, + paramsSerializer, + responseSchema: CrowdstrikeHostActionsResponseSchema, }, - paramsSerializer, - responseSchema: CrowdstrikeHostActionsResponseSchema, - }); + connectorUsageCollector + ); } public async getAgentDetails( - payload: CrowdstrikeGetAgentsParams + payload: CrowdstrikeGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.crowdstrikeApiRequest({ - url: this.urls.agents, - method: 'GET', - params: { - ids: payload.ids, + return this.crowdstrikeApiRequest( + { + url: this.urls.agents, + method: 'GET', + params: { + ids: payload.ids, + }, + paramsSerializer, + responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, }, - paramsSerializer, - responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, - }) as Promise; + connectorUsageCollector + ) as Promise; } public async getAgentOnlineStatus( - payload: CrowdstrikeGetAgentsParams + payload: CrowdstrikeGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.crowdstrikeApiRequest({ - url: this.urls.agentStatus, - method: 'GET', - params: { - ids: payload.ids, + return this.crowdstrikeApiRequest( + { + url: this.urls.agentStatus, + method: 'GET', + params: { + ids: payload.ids, + }, + paramsSerializer, + responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, }, - paramsSerializer, - responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, - }) as Promise; + connectorUsageCollector + ) as Promise; } - private async getTokenRequest() { - const response = await this.request({ - url: this.urls.getToken, - method: 'post', - headers: { - accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - authorization: 'Basic ' + CrowdstrikeConnector.base64encodedToken, + private async getTokenRequest(connectorUsageCollector: ConnectorUsageCollector) { + const response = await this.request( + { + url: this.urls.getToken, + method: 'post', + headers: { + accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + authorization: 'Basic ' + CrowdstrikeConnector.base64encodedToken, + }, + responseSchema: CrowdstrikeGetTokenResponseSchema, }, - responseSchema: CrowdstrikeGetTokenResponseSchema, - }); + connectorUsageCollector + ); const token = response.data?.access_token; if (token) { // Clear any existing timeout @@ -173,28 +193,33 @@ export class CrowdstrikeConnector extends SubActionConnector< private async crowdstrikeApiRequest( req: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector, retried?: boolean ): Promise { try { if (!CrowdstrikeConnector.token) { - CrowdstrikeConnector.token = (await this.getTokenRequest()) as string; + CrowdstrikeConnector.token = (await this.getTokenRequest( + connectorUsageCollector + )) as string; } - const response = await this.request({ - ...req, - headers: { - ...req.headers, - Authorization: `Bearer ${CrowdstrikeConnector.token}`, + const response = await this.request( + { + ...req, + headers: { + ...req.headers, + Authorization: `Bearer ${CrowdstrikeConnector.token}`, + }, }, - }); + connectorUsageCollector + ); return response.data; } catch (error) { if (error.code === 401 && !retried) { CrowdstrikeConnector.token = null; - return this.crowdstrikeApiRequest(req, true); + return this.crowdstrikeApiRequest(req, connectorUsageCollector, true); } - throw new CrowdstrikeError(error.message); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts index 6f1a002cdf1d0..055a7fe7a7dba 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts @@ -11,6 +11,7 @@ import { D3_SECURITY_CONNECTOR_ID } from '../../../common/d3security/constants'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { D3SecurityRunActionResponseSchema } from '../../../common/d3security/schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; describe('D3SecurityConnector', () => { const sampleBody = JSON.stringify({ @@ -28,6 +29,7 @@ describe('D3SecurityConnector', () => { const mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); }); + const logger = loggingSystemMock.createLogger(); describe('D3 Security', () => { const connector = new D3SecurityConnector({ @@ -35,26 +37,35 @@ describe('D3SecurityConnector', () => { connector: { id: '1', type: D3_SECURITY_CONNECTOR_ID }, config: { url: 'https://example.com/api' }, secrets: { token: '123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); + let connectorUsageCollector: ConnectorUsageCollector; + beforeEach(() => { // @ts-ignore connector.request = mockRequest; jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('the D3 Security API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: sampleBody }); + const response = await connector.runApi({ body: sampleBody }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api', - method: 'post', - responseSchema: D3SecurityRunActionResponseSchema, - data: sampleBodyFormatted, - headers: { - d3key: '123', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api', + method: 'post', + responseSchema: D3SecurityRunActionResponseSchema, + data: sampleBodyFormatted, + headers: { + d3key: '123', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ result: 'success' }); }); @@ -62,7 +73,9 @@ describe('D3SecurityConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: sampleBody })).rejects.toThrow('API Error'); + await expect(connector.runApi({ body: sampleBody }, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts index 804590c01b284..0c35766a3ddf3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts @@ -7,6 +7,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { addSeverityAndEventTypeInBody } from './helpers'; import { D3SecurityRunActionParamsSchema, @@ -57,22 +58,24 @@ export class D3SecurityConnector extends SubActionConnector { - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: D3SecurityRunActionResponseSchema, - data: addSeverityAndEventTypeInBody( - body ?? '', - severity ?? D3SecuritySeverity.EMPTY, - eventType ?? '' - ), - headers: { d3key: this.token || '' }, - }); + public async runApi( + { body, severity, eventType }: D3SecurityRunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: D3SecurityRunActionResponseSchema, + data: addSeverityAndEventTypeInBody( + body ?? '', + severity ?? D3SecuritySeverity.EMPTY, + eventType ?? '' + ), + headers: { d3key: this.token || '' }, + }, + connectorUsageCollector + ); return response.data; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts index f3787e8d367d9..4ee4b3e4890b7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts @@ -20,6 +20,8 @@ import { validateParams, validateSecrets, } from '@kbn/actions-plugin/server/lib'; + +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { sendEmail } from './send_email'; import { ActionParamsType, @@ -514,6 +516,10 @@ describe('execute()', () => { text: 'Go to Elastic', }, }; + const connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); const actionId = 'some-id'; const executorOptions: EmailConnectorTypeExecutorOptions = { @@ -524,6 +530,7 @@ describe('execute()', () => { services, configurationUtilities: actionsConfigMock.create(), logger: mockedLogger, + connectorUsageCollector, }; beforeEach(() => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index 785ace370323f..3a1d01732eb7d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -274,8 +274,16 @@ async function executor( }, execOptions: EmailConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, secrets, params, configurationUtilities, services, logger } = - execOptions; + const { + actionId, + config, + secrets, + params, + configurationUtilities, + services, + logger, + connectorUsageCollector, + } = execOptions; const connectorTokenClient = services.connectorTokenClient; const emails = params.to.concat(params.cc).concat(params.bcc); @@ -366,7 +374,12 @@ async function executor( let result; try { - result = await sendEmail(logger, sendEmailOptions, connectorTokenClient); + result = await sendEmail( + logger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.email.errorSendingErrorMessage', { defaultMessage: 'error sending email', diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts index 535c3932c04e7..77de60660a975 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts @@ -10,7 +10,7 @@ import { Logger } from '@kbn/core/server'; import { sendEmail } from './send_email'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import nodemailer from 'nodemailer'; -import { ProxySettings } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ProxySettings } from '@kbn/actions-plugin/server/types'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { CustomHostSettings } from '@kbn/actions-plugin/server/config'; import { sendEmailGraphApi } from './send_email_graph_api'; @@ -39,6 +39,7 @@ const sendMailMock = jest.fn(); const mockLogger = loggingSystemMock.create().get() as jest.Mocked; const connectorTokenClient = connectorTokenClientMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; describe('send_email module', () => { beforeEach(() => { @@ -53,11 +54,21 @@ describe('send_email module', () => { interceptors: mockAxiosInstanceInterceptor, }; }); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockLogger, + connectorId: 'test-connector-id', + }); }); test('handles authenticated email using service', async () => { const sendEmailOptions = getSendEmailOptions({ transport: { service: 'other' } }); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -101,7 +112,12 @@ describe('send_email module', () => { content: { hasHTMLMessage: true }, transport: { service: 'other' }, }); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -159,7 +175,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -176,6 +192,7 @@ describe('send_email module', () => { delete sendEmailGraphApiMock.mock.calls[0][0].options.configurationUtilities; sendEmailGraphApiMock.mock.calls[0].pop(); sendEmailGraphApiMock.mock.calls[0].pop(); + sendEmailGraphApiMock.mock.calls[0].pop(); expect(sendEmailGraphApiMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { @@ -254,7 +271,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -292,7 +309,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -322,7 +339,7 @@ describe('send_email module', () => { getOAuthClientCredentialsAccessTokenMock.mockReturnValueOnce(null); await expect(() => - sendEmail(mockLogger, sendEmailOptions, connectorTokenClient) + sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unable to retrieve access token for connectorId: 1"` ); @@ -362,7 +379,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -412,7 +434,12 @@ describe('send_email module', () => { delete sendEmailOptions.transport.user; // @ts-expect-error delete sendEmailOptions.transport.password; - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -462,7 +489,12 @@ describe('send_email module', () => { // @ts-expect-error delete sendEmailOptions.transport.password; - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -503,9 +535,9 @@ describe('send_email module', () => { sendMailMock.mockReset(); sendMailMock.mockRejectedValue(new Error('wops')); - await expect(sendEmail(mockLogger, sendEmailOptions, connectorTokenClient)).rejects.toThrow( - 'wops' - ); + await expect( + sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector) + ).rejects.toThrow('wops'); }); test('it bypasses with proxyBypassHosts when expected', async () => { @@ -526,7 +558,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -560,7 +597,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -596,7 +638,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -630,7 +677,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -667,7 +719,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); // note in the object below, the rejectUnauthenticated got set to false, @@ -710,7 +767,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); // in this case, rejectUnauthorized is true, as the custom host settings @@ -757,7 +819,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -791,7 +858,7 @@ describe('send_email module', () => { 'Bearer clienttokentokentoken' ); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(createAxiosInstanceMock).toHaveBeenCalledTimes(1); expect(createAxiosInstanceMock).toHaveBeenCalledWith(); expect(mockAxiosInstanceInterceptor.response.use).toHaveBeenCalledTimes(1); @@ -834,7 +901,7 @@ describe('send_email module', () => { 'Bearer clienttokentokentoken' ); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(createAxiosInstanceMock).toHaveBeenCalledTimes(1); expect(createAxiosInstanceMock).toHaveBeenCalledWith(); expect(mockAxiosInstanceInterceptor.response.use).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts index f3ab3bfa22c55..199d96f352389 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts @@ -17,7 +17,11 @@ import { getNodeSSLOptions, getSSLSettingsFromConfig, } from '@kbn/actions-plugin/server/lib/get_node_ssl_options'; -import { ConnectorTokenClientContract, ProxySettings } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, + ProxySettings, +} from '@kbn/actions-plugin/server/types'; import { getOAuthClientCredentialsAccessToken } from '@kbn/actions-plugin/server/lib/get_oauth_client_credentials_access_token'; import { AdditionalEmailServices } from '../../../common'; import { sendEmailGraphApi } from './send_email_graph_api'; @@ -66,7 +70,8 @@ export interface Content { export async function sendEmail( logger: Logger, options: SendEmailOptions, - connectorTokenClient: ConnectorTokenClientContract + connectorTokenClient: ConnectorTokenClientContract, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, content } = options; const { message, messageHTML } = content; @@ -74,9 +79,15 @@ export async function sendEmail( const renderedMessage = messageHTML ?? htmlFromMarkdown(logger, message); if (transport.service === AdditionalEmailServices.EXCHANGE) { - return await sendEmailWithExchange(logger, options, renderedMessage, connectorTokenClient); + return await sendEmailWithExchange( + logger, + options, + renderedMessage, + connectorTokenClient, + connectorUsageCollector + ); } else { - return await sendEmailWithNodemailer(logger, options, renderedMessage); + return await sendEmailWithNodemailer(logger, options, renderedMessage, connectorUsageCollector); } } @@ -85,7 +96,8 @@ export async function sendEmailWithExchange( logger: Logger, options: SendEmailOptions, messageHTML: string, - connectorTokenClient: ConnectorTokenClientContract + connectorTokenClient: ConnectorTokenClientContract, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, configurationUtilities, connectorId } = options; const { clientId, clientSecret, tenantId, oauthTokenUrl } = transport; @@ -155,6 +167,7 @@ export async function sendEmailWithExchange( }, logger, configurationUtilities, + connectorUsageCollector, axiosInstance ); } @@ -163,7 +176,8 @@ export async function sendEmailWithExchange( async function sendEmailWithNodemailer( logger: Logger, options: SendEmailOptions, - messageHTML: string + messageHTML: string, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, routing, content, configurationUtilities, hasAuth } = options; const { service } = transport; @@ -186,6 +200,7 @@ async function sendEmailWithNodemailer( // some deep properties, so need to use any here. const transportConfig = getTransportConfig(configurationUtilities, logger, transport, hasAuth); const nodemailerTransport = nodemailer.createTransport(transportConfig); + connectorUsageCollector.addRequestBodyBytes(undefined, email); const result = await nodemailerTransport.sendMail(email); if (service === JSON_TRANSPORT_SERVICE) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts index 03289b79c3004..6166082345243 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts @@ -14,7 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { CustomHostSettings } from '@kbn/actions-plugin/server/config'; -import { ProxySettings } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ProxySettings } from '@kbn/actions-plugin/server/types'; import { sendEmailGraphApi } from './send_email_graph_api'; const createAxiosInstanceMock = axios.create as jest.Mock; @@ -28,6 +28,11 @@ describe('sendEmailGraphApi', () => { const configurationUtilities = actionsConfigMock.create(); test('email contains the proper message', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -38,7 +43,8 @@ describe('sendEmailGraphApi', () => { headers: {}, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -118,6 +124,10 @@ describe('sendEmailGraphApi', () => { }); test('email was sent on behalf of the user "from" mailbox', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -128,7 +138,8 @@ describe('sendEmailGraphApi', () => { headers: { Authorization: 'Bearer 1234567' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[1]).toMatchInlineSnapshot(` Array [ @@ -210,6 +221,10 @@ describe('sendEmailGraphApi', () => { }); test('sendMail request was sent to the custom configured Graph API URL', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -221,7 +236,8 @@ describe('sendEmailGraphApi', () => { headers: {}, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[2]).toMatchInlineSnapshot(` Array [ @@ -301,6 +317,10 @@ describe('sendEmailGraphApi', () => { }); test('throw the exception and log the proper error if message was not sent successfuly', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 400, data: { @@ -315,7 +335,8 @@ describe('sendEmailGraphApi', () => { sendEmailGraphApi( { options: getSendEmailOptions(), messageHTML: 'test1', headers: {} }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).rejects.toThrowErrorMatchingInlineSnapshot( '"{\\"error\\":{\\"code\\":\\"ErrorMimeContentInvalidBase64String\\",\\"message\\":\\"Invalid base64 string for MIME content.\\"}}"' diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts index 79d7af05e041e..ed624299b3535 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts @@ -11,18 +11,14 @@ import axios, { AxiosInstance, AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SendEmailOptions } from './send_email'; -interface SendEmailGraphApiOptions { - options: SendEmailOptions; - headers: Record; - messageHTML: string; -} - export async function sendEmailGraphApi( sendEmailOptions: SendEmailGraphApiOptions, logger: Logger, configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector, axiosInstance?: AxiosInstance ): Promise { const { options, headers, messageHTML } = sendEmailOptions; @@ -42,6 +38,7 @@ export async function sendEmailGraphApi( headers, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); if (res.status === 202) { return res.data; @@ -53,6 +50,12 @@ export async function sendEmailGraphApi( throw new Error(errString); } +interface SendEmailGraphApiOptions { + options: SendEmailOptions; + headers: Record; + messageHTML: string; +} + function getMessage(emailOptions: SendEmailOptions, messageHTML: string) { const { routing, content } = emailOptions; const { to, cc, bcc } = routing; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts index 2b3fab30432fa..5b7353ef58291 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts @@ -7,6 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { validateConfig, validateParams } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { ActionParamsType, @@ -27,11 +28,16 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: ESIndexConnectorType; let configurationUtilities: ActionsConfigurationUtilities; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.resetAllMocks(); configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -185,6 +191,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const scopedClusterClient = elasticsearchClientMock .createClusterClient() @@ -230,6 +237,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ @@ -280,6 +288,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); @@ -324,6 +333,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ @@ -656,6 +666,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -695,6 +706,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -757,6 +769,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -824,6 +837,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts index d58cefe12f839..949ae0a6c1bd2 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts @@ -15,6 +15,7 @@ import { RunApiResponseSchema, StreamingResponseSchema } from '../../../common/g import { DEFAULT_GEMINI_MODEL } from '../../../common/gemini/constants'; import { AxiosError } from 'axios'; import { Transform } from 'stream'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); jest.mock('@kbn/actions-plugin/server/sub_action_framework/helpers/validators', () => ({ @@ -61,6 +62,7 @@ describe('GeminiConnector', () => { mockRequest = connector.request = jest.fn().mockResolvedValue(defaultResponse); }); + const logger = loggingSystemMock.createLogger(); const connector = new GeminiConnector({ connector: { id: '1', type: '.gemini' }, configurationUtilities: actionsConfigMock.create(), @@ -84,14 +86,19 @@ describe('GeminiConnector', () => { client_x509_cert_url: '', }), }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); + let connectorUsageCollector: ConnectorUsageCollector; describe('Gemini', () => { beforeEach(() => { // @ts-ignore connector.request = mockRequest; + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('runApi', () => { @@ -101,33 +108,36 @@ describe('GeminiConnector', () => { model: DEFAULT_GEMINI_MODEL, }; - const response = await connector.runApi(runActionParams); + const response = await connector.runApi(runActionParams, connectorUsageCollector); // Assertions expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - data: JSON.stringify({ - messages: [ - { - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], - }, - ], - }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + data: JSON.stringify({ + messages: [ + { + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + timeout: 60000, + responseSchema: RunApiResponseSchema, + signal: undefined, }, - timeout: 60000, - responseSchema: RunApiResponseSchema, - signal: undefined, - }); + connectorUsageCollector + ); expect(response).toEqual(connectorResponse); }); @@ -144,66 +154,72 @@ describe('GeminiConnector', () => { }; it('the API call is successful with correct parameters', async () => { - await connector.invokeAI(aiAssistantBody); + await connector.invokeAI(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - responseSchema: RunApiResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal: undefined, + timeout: 60000, }, - signal: undefined, - timeout: 60000, - }); + connectorUsageCollector + ); }); it('signal and timeout is properly passed to runApi', async () => { const signal = jest.fn(); const timeout = 60000; - await connector.invokeAI({ ...aiAssistantBody, timeout, signal }); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - responseSchema: RunApiResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + await connector.invokeAI({ ...aiAssistantBody, timeout, signal }, connectorUsageCollector); + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal, + timeout: 60000, }, - signal, - timeout: 60000, - }); + connectorUsageCollector + ); }); }); @@ -226,68 +242,77 @@ describe('GeminiConnector', () => { }; it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - responseType: 'stream', - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal: undefined, + timeout: 60000, }, - signal: undefined, - timeout: 60000, - }); + connectorUsageCollector + ); }); it('signal and timeout is properly passed to streamApi', async () => { const signal = jest.fn(); const timeout = 60000; - await connector.invokeStream({ ...aiAssistantBody, timeout, signal }); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + await connector.invokeStream( + { ...aiAssistantBody, timeout, signal }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - responseType: 'stream', - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal, + timeout: 60000, }, - signal, - timeout: 60000, - }); + connectorUsageCollector + ); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts index 6cb4671b7aeeb..75f7458d3d6b3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts @@ -11,7 +11,10 @@ import { PassThrough } from 'stream'; import { IncomingMessage } from 'http'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { getGoogleOAuthJwtAccessToken } from '@kbn/actions-plugin/server/lib/get_gcp_oauth_access_token'; -import { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, +} from '@kbn/actions-plugin/server/types'; import { HarmBlockThreshold, HarmCategory } from '@google/generative-ai'; import { @@ -211,13 +214,10 @@ export class GeminiConnector extends SubActionConnector { * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async runApi({ - body, - model: reqModel, - signal, - timeout, - raw, - }: RunActionParams): Promise { + public async runApi( + { body, model: reqModel, signal, timeout, raw }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const currentModel = reqModel ?? this.model; const path = `/v1/projects/${this.gcpProjectID}/locations/${this.gcpRegion}/publishers/google/models/${currentModel}:generateContent`; @@ -236,7 +236,7 @@ export class GeminiConnector extends SubActionConnector { responseSchema: raw ? RunActionRawResponseSchema : RunApiResponseSchema, } as SubActionRequestParams; - const response = await this.request(requestArgs); + const response = await this.request(requestArgs, connectorUsageCollector); if (raw) { return response.data; @@ -249,65 +249,65 @@ export class GeminiConnector extends SubActionConnector { return { completion: completionText, usageMetadata }; } - private async streamAPI({ - body, - model: reqModel, - signal, - timeout, - }: RunActionParams): Promise { + private async streamAPI( + { body, model: reqModel, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const currentModel = reqModel ?? this.model; const path = `/v1/projects/${this.gcpProjectID}/locations/${this.gcpRegion}/publishers/google/models/${currentModel}:streamGenerateContent?alt=sse`; const token = await this.getAccessToken(); - const response = await this.request({ - url: `${this.url}${path}`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: body, - responseType: 'stream', - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', + const response = await this.request( + { + url: `${this.url}${path}`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: body, + responseType: 'stream', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + signal, + timeout: timeout ?? DEFAULT_TIMEOUT_MS, }, - signal, - timeout: timeout ?? DEFAULT_TIMEOUT_MS, - }); + connectorUsageCollector + ); return response.data.pipe(new PassThrough()); } - public async invokeAI({ - messages, - model, - temperature = 0, - signal, - timeout, - }: InvokeAIActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify(formatGeminiPayload(messages, temperature)), - model, - signal, - timeout, - }); + public async invokeAI( + { messages, model, temperature = 0, signal, timeout }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify(formatGeminiPayload(messages, temperature)), + model, + signal, + timeout, + }, + connectorUsageCollector + ); return { message: res.completion, usageMetadata: res.usageMetadata }; } - public async invokeAIRaw({ - messages, - model, - temperature = 0, - signal, - timeout, - tools, - }: InvokeAIRawActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), - model, - signal, - timeout, - raw: true, - }); + public async invokeAIRaw( + { messages, model, temperature = 0, signal, timeout, tools }: InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), + model, + signal, + timeout, + raw: true, + }, + connectorUsageCollector + ); return res; } @@ -320,22 +320,28 @@ export class GeminiConnector extends SubActionConnector { * @param messages An array of messages to be sent to the API * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async invokeStream({ - messages, - model, - stopSequences, - temperature = 0, - signal, - timeout, - tools, - }: InvokeAIActionParams): Promise { - return (await this.streamAPI({ - body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), + public async invokeStream( + { + messages, model, stopSequences, + temperature = 0, signal, timeout, - })) as unknown as IncomingMessage; + tools, + }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + return (await this.streamAPI( + { + body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), + model, + stopSequences, + signal, + timeout, + }, + connectorUsageCollector + )) as unknown as IncomingMessage; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts index 630c0973935cd..1481ab8601fa6 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts @@ -95,7 +95,15 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: JiraExecutorResultData | null = null; @@ -105,7 +113,8 @@ async function executor( secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts index 34e0f1f799ce5..5e98bdc96c0ee 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts @@ -14,6 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; interface ResponseError extends Error { @@ -135,8 +136,13 @@ const mockOldAPI = () => describe('Jira service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { // The trailing slash at the end of the url is intended. @@ -145,7 +151,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -162,7 +169,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -175,7 +183,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -188,7 +197,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -201,7 +211,8 @@ describe('Jira service', () => { secrets: { email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -213,7 +224,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -258,6 +270,7 @@ describe('Jira service', () => { url: 'https://coolsite.net/rest/api/2/issue/1', logger, configurationUtilities, + connectorUsageCollector, }); }); @@ -401,6 +414,7 @@ describe('Jira service', () => { priority: { name: 'High' }, }, }, + connectorUsageCollector, }); }); @@ -459,6 +473,7 @@ describe('Jira service', () => { priority: { name: 'High' }, }, }, + connectorUsageCollector, }); }); @@ -492,6 +507,7 @@ describe('Jira service', () => { parent: { key: 'RJ-107' }, }, }, + connectorUsageCollector, }); }); @@ -561,6 +577,7 @@ describe('Jira service', () => { ...otherFields, }, }, + connectorUsageCollector, }); }); }); @@ -631,6 +648,7 @@ describe('Jira service', () => { parent: { key: 'RJ-107' }, }, }, + connectorUsageCollector, }); }); @@ -693,6 +711,7 @@ describe('Jira service', () => { ...otherFields, }, }, + connectorUsageCollector, }); }); }); @@ -746,6 +765,7 @@ describe('Jira service', () => { configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/1/comment', data: { body: 'comment' }, + connectorUsageCollector, }); }); @@ -802,6 +822,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/capabilities', + connectorUsageCollector, }); }); @@ -883,6 +904,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta?projectKeys=CK&expand=projects.issuetypes.fields', + connectorUsageCollector, }); }); @@ -957,6 +979,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta/CK/issuetypes', + connectorUsageCollector, }); }); @@ -1032,6 +1055,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta?projectKeys=CK&issuetypeIds=10006&expand=projects.issuetypes.fields', + connectorUsageCollector, }); }); @@ -1240,6 +1264,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/search?jql=project%3D%22CK%22%20and%20summary%20~%22Test%20title%22`, + connectorUsageCollector, }); }); @@ -1266,6 +1291,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/search?jql=project%3D%22CK%22%20and%20summary%20~%22%5C%5C%5Bth%5C%5C!s%5C%5C%5Eis%5C%5C(%5C%5C)a%5C%5C-te%5C%5C%2Bst%5C%5C-%5C%5C%7B%5C%5C~is%5C%5C*s%5C%5C%26ue%5C%5C%3For%5C%5C%7Cand%5C%5Cbye%5C%5C%3A%5C%5C%7D%5C%5C%5D%5C%5C%7D%5C%5C%5D%22`, + connectorUsageCollector, }); }); @@ -1344,6 +1370,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/issue/RJ-107`, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts index 3cd5115234da1..064667558b37e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts @@ -16,6 +16,7 @@ import { } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { CreateCommentParams, CreateIncidentParams, @@ -47,7 +48,8 @@ const createMetaCapabilities = ['list-project-issuetypes', 'list-issuetype-field export const createExternalService = ( { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { apiUrl: url, projectKey } = config as JiraPublicConfigurationType; const { apiToken, email } = secrets as JiraSecretConfigurationType; @@ -189,6 +191,7 @@ export const createExternalService = ( url: `${incidentUrl}/${id}`, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -242,6 +245,7 @@ export const createExternalService = ( fields, }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -288,6 +292,7 @@ export const createExternalService = ( logger, data: { fields }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -326,6 +331,7 @@ export const createExternalService = ( logger, data: { body: comment.comment }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -358,6 +364,7 @@ export const createExternalService = ( url: capabilitiesUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -389,6 +396,7 @@ export const createExternalService = ( url: getIssueTypesOldAPIURL, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -404,6 +412,7 @@ export const createExternalService = ( url: getIssueTypesUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -436,6 +445,7 @@ export const createExternalService = ( url: createGetIssueTypeFieldsUrl(getIssueTypeFieldsOldAPIURL, issueTypeId), logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -515,6 +525,7 @@ export const createExternalService = ( url: query, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -543,6 +554,7 @@ export const createExternalService = ( url: getIssueUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts index 311de65eb4abe..4f6133891c431 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts @@ -12,6 +12,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { connectorTokenClientMock } from '@kbn/actions-plugin/server/lib/connector_token_client.mock'; import { snExternalServiceConfig } from './config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; const connectorTokenClient = connectorTokenClientMock.create(); @@ -19,10 +20,15 @@ const configurationUtilities = actionsConfigMock.create(); jest.mock('axios'); axios.create = jest.fn(() => axios); +let connectorUsageCollector: ConnectorUsageCollector; describe('createServiceWrapper', () => { beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); test('creates axios instance with apiUrl', () => { @@ -45,6 +51,7 @@ describe('createServiceWrapper', () => { serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }); expect(createServiceFn).toHaveBeenCalledWith({ @@ -53,6 +60,7 @@ describe('createServiceWrapper', () => { configurationUtilities, serviceConfig, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -76,6 +84,7 @@ describe('createServiceWrapper', () => { serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }); expect(createServiceFn).toHaveBeenCalledWith({ @@ -84,6 +93,7 @@ describe('createServiceWrapper', () => { configurationUtilities, serviceConfig, axiosInstance: axios, + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts index f2de6e3787f70..dbadbf66f8d5f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts @@ -6,7 +6,10 @@ */ import { Logger } from '@kbn/core/server'; -import type { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, +} from '@kbn/actions-plugin/server/types'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { ExternalService, ExternalServiceCredentials, SNProductsConfigValue } from './types'; @@ -21,6 +24,7 @@ interface CreateServiceWrapperOpts { serviceConfig: SNProductsConfigValue; connectorTokenClient: ConnectorTokenClientContract; createServiceFn: ServiceFactory; + connectorUsageCollector: ConnectorUsageCollector; } export function createServiceWrapper({ @@ -31,6 +35,7 @@ export function createServiceWrapper({ serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }: CreateServiceWrapperOpts): T { const { config } = credentials; const { apiUrl: url } = config as ServiceNowPublicConfigurationType; @@ -50,5 +55,6 @@ export function createServiceWrapper({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts index ce6f33e1cc0d1..aa8d248566d9a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { serviceNowCommonFields, serviceNowChoices } from './mocks'; import { snExternalServiceConfig } from './config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios', () => ({ @@ -178,6 +179,7 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -191,6 +193,7 @@ const expectImportedIncident = (update: boolean) => { u_description: 'desc', ...(update ? { elastic_incident_id: '1' } : {}), }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -199,14 +202,21 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; describe('ServiceNow service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + service = createExternalService({ credentials: { // The trailing slash at the end of the url is intended. @@ -218,6 +228,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }); }); @@ -233,6 +244,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -273,6 +285,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -437,6 +450,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -464,6 +478,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -477,6 +492,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -490,6 +506,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -535,6 +552,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); }); @@ -559,6 +577,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -572,6 +591,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); }); @@ -625,6 +645,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await createIncident(service); @@ -635,6 +656,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -644,6 +666,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -652,6 +675,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -707,6 +731,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_inc_int_elastic_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', foo: 'test' }, + connectorUsageCollector, }); }); }); @@ -723,6 +748,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -749,6 +775,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -762,6 +789,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -778,6 +806,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -826,6 +855,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await updateIncident(service); @@ -835,6 +865,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -844,6 +875,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', elastic_incident_id: '1' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -852,6 +884,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -915,6 +948,7 @@ describe('ServiceNow service', () => { elastic_incident_id: '1', foo: 'test', }, + connectorUsageCollector, }); }); }); @@ -931,6 +965,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -958,6 +993,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -971,6 +1007,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -988,6 +1025,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -1032,6 +1070,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1040,6 +1079,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1054,6 +1094,7 @@ describe('ServiceNow service', () => { u_state: '7', u_close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(4, { @@ -1062,6 +1103,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=incident.do?sys_id=1'); @@ -1097,6 +1139,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1105,6 +1148,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1119,6 +1163,7 @@ describe('ServiceNow service', () => { u_state: '7', u_close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(4, { @@ -1127,6 +1172,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=incident.do?sys_id=1'); @@ -1237,6 +1283,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -1268,6 +1315,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -1285,6 +1333,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1298,6 +1347,7 @@ describe('ServiceNow service', () => { state: '7', close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1306,6 +1356,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -1325,6 +1376,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -1346,6 +1398,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -1358,6 +1411,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=sn_si_incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -1394,6 +1448,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1415,6 +1470,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -1428,6 +1484,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=sn_si_incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1520,6 +1577,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); await service.checkIfApplicationIsInstalled(); expect(requestMock).not.toHaveBeenCalled(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts index 42aed9dcf8466..84a8592aaa832 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts @@ -37,6 +37,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalService => { const { config, secrets } = credentials; const { table, importSetTable, useImportAPI, appScope } = serviceConfig; @@ -132,6 +133,7 @@ export const createExternalService: ServiceFactory = ({ logger, configurationUtilities, method: 'get', + connectorUsageCollector, // TODO check if this is internal }); checkInstance(res); @@ -160,6 +162,7 @@ export const createExternalService: ServiceFactory = ({ logger, configurationUtilities, method: 'get', + connectorUsageCollector, }); checkInstance(res); @@ -178,6 +181,7 @@ export const createExternalService: ServiceFactory = ({ logger, params, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -201,6 +205,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data: prepareIncident(useTableApi, incident), configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -240,6 +245,7 @@ export const createExternalService: ServiceFactory = ({ ...(useTableApi ? {} : { elastic_incident_id: incidentId }), }, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -272,6 +278,7 @@ export const createExternalService: ServiceFactory = ({ method: 'get', logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -350,6 +357,7 @@ export const createExternalService: ServiceFactory = ({ url: fieldsUrl, logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -367,6 +375,7 @@ export const createExternalService: ServiceFactory = ({ url: getChoicesURL(fields), logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); return res.data.result; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts index 86d037c324e41..7cecf0bcddb46 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts @@ -11,7 +11,7 @@ import { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; import { TypeOf } from '@kbn/config-schema'; import { Logger } from '@kbn/core/server'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; -import { ValidatorServices } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ValidatorServices } from '@kbn/actions-plugin/server/types'; import { ExecutorParamsSchemaITSM, ExecutorSubActionCommonFieldsParamsSchema, @@ -305,6 +305,7 @@ interface ServiceFactoryOpts { configurationUtilities: ActionsConfigurationUtilities; serviceConfig: SNProductsConfigValue; axiosInstance: AxiosInstance; + connectorUsageCollector: ConnectorUsageCollector; } export type ServiceFactory = ({ @@ -313,6 +314,7 @@ export type ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }: ServiceFactoryOpts) => T; /** diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts index 6f0974fe1796d..87dacaf4e6f17 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts @@ -19,6 +19,7 @@ import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { RunActionResponseSchema, StreamingResponseSchema } from '../../../common/openai/schema'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { PassThrough, Transform } from 'stream'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); const mockTee = jest.fn(); @@ -46,6 +47,9 @@ jest.mock('openai', () => ({ describe('OpenAIConnector', () => { let mockRequest: jest.Mock; let mockError: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; + + const logger = loggingSystemMock.createLogger(); const mockResponseString = 'Hello! How can I assist you today?'; const mockResponse = { headers: {}, @@ -72,6 +76,10 @@ describe('OpenAIConnector', () => { }, }; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); mockRequest = jest.fn().mockResolvedValue(mockResponse); mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); @@ -92,7 +100,7 @@ describe('OpenAIConnector', () => { }, }, secrets: { apiKey: '123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); @@ -113,48 +121,74 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('uses the default model if none is supplied', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('overrides the default model with the default model specified in the body', async () => { const requestBody = { model: 'gpt-3.5-turbo', ...sampleOpenAiBody }; - const response = await connector.runApi({ body: JSON.stringify(requestBody) }); + const response = await connector.runApi( + { body: JSON.stringify(requestBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...requestBody, stream: false }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ ...requestBody, stream: false }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the OpenAI API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -168,25 +202,31 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.runApi({ - body: JSON.stringify({ - ...body, - stream: true, - }), - }); + const response = await connector.runApi( + { + body: JSON.stringify({ + ...body, + stream: true, + }), + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ - ...body, - stream: false, - }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...body, + stream: false, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -194,51 +234,71 @@ describe('OpenAIConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: JSON.stringify(sampleOpenAiBody) })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('streamApi', () => { it('the OpenAI API call is successful with correct parameters when stream = false', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleOpenAiBody), - stream: false, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleOpenAiBody), + stream: false, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: RunActionResponseSchema, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: RunActionResponseSchema, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the OpenAI API call is successful with correct parameters when stream = true', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleOpenAiBody), - stream: true, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleOpenAiBody), + stream: true, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -255,29 +315,35 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.streamApi({ - body: JSON.stringify({ - ...body, - stream: false, - }), - stream: true, - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - ...body, + const response = await connector.streamApi( + { + body: JSON.stringify({ + ...body, + stream: false, + }), stream: true, - }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', }, - }); + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...body, + stream: true, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + }, + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -289,7 +355,10 @@ describe('OpenAIConnector', () => { connector.request = mockError; await expect( - connector.streamApi({ body: JSON.stringify(sampleOpenAiBody), stream: true }) + connector.streamApi( + { body: JSON.stringify(sampleOpenAiBody), stream: true }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); @@ -314,135 +383,181 @@ describe('OpenAIConnector', () => { }); it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(sampleOpenAiBody); + await connector.invokeStream(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); }); it('signal is properly passed to streamApi', async () => { const signal = jest.fn(); - await connector.invokeStream({ ...sampleOpenAiBody, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', - }, - signal, - }); + await connector.invokeStream({ ...sampleOpenAiBody, signal }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + signal, + }, + connectorUsageCollector + ); }); it('timeout is properly passed to streamApi', async () => { const timeout = 180000; - await connector.invokeStream({ ...sampleOpenAiBody, timeout }); - - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', - }, - timeout, - }); + await connector.invokeStream({ ...sampleOpenAiBody, timeout }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + timeout, + }, + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeStream(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeStream(sampleOpenAiBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); it('responds with a readable stream', async () => { // @ts-ignore connector.request = mockStream(); - const response = await connector.invokeStream(sampleOpenAiBody); + const response = await connector.invokeStream(sampleOpenAiBody, connectorUsageCollector); expect(response instanceof PassThrough).toEqual(true); }); }); describe('invokeAI', () => { it('the API call is successful with correct parameters', async () => { - const response = await connector.invokeAI(sampleOpenAiBody); + const response = await connector.invokeAI(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); expect(response.usage.total_tokens).toEqual(9); }); it('signal is properly passed to runApi', async () => { const signal = jest.fn(); - await connector.invokeAI({ ...sampleOpenAiBody, signal }); + await connector.invokeAI({ ...sampleOpenAiBody, signal }, connectorUsageCollector); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + signal, }, - signal, - }); + connectorUsageCollector + ); }); it('timeout is properly passed to runApi', async () => { const timeout = 180000; - await connector.invokeAI({ ...sampleOpenAiBody, timeout }); + await connector.invokeAI({ ...sampleOpenAiBody, timeout }, connectorUsageCollector); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + timeout, }, - timeout, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeAI(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect(connector.invokeAI(sampleOpenAiBody, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); describe('invokeAsyncIterator', () => { it('the API call is successful with correct request parameters', async () => { - await connector.invokeAsyncIterator(sampleOpenAiBody); + await connector.invokeAsyncIterator(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(0); expect(mockCreate).toHaveBeenCalledWith( { @@ -457,7 +572,10 @@ describe('OpenAIConnector', () => { it('signal and timeout is properly passed', async () => { const timeout = 180000; const signal = jest.fn(); - await connector.invokeAsyncIterator({ ...sampleOpenAiBody, signal, timeout }); + await connector.invokeAsyncIterator( + { ...sampleOpenAiBody, signal, timeout }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(0); expect(mockCreate).toHaveBeenCalledWith( { @@ -478,7 +596,9 @@ describe('OpenAIConnector', () => { throw new Error('API Error'); }); - await expect(connector.invokeAsyncIterator(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeAsyncIterator(sampleOpenAiBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('getResponseErrorMessage', () => { @@ -568,16 +688,26 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('uses the default model if none is supplied', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); }); @@ -614,17 +744,23 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('test the AzureAI API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleAzureAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleAzureAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -637,19 +773,25 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.runApi({ - body: JSON.stringify({ ...body, stream: true }), - }); + const response = await connector.runApi( + { + body: JSON.stringify({ ...body, stream: true }), + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -657,49 +799,61 @@ describe('OpenAIConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: JSON.stringify(sampleAzureAiBody) })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.runApi({ body: JSON.stringify(sampleAzureAiBody) }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('streamApi', () => { it('the AzureAI API call is successful with correct parameters when stream = false', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleAzureAiBody), - stream: false, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleAzureAiBody), + stream: false, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: RunActionResponseSchema, - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: RunActionResponseSchema, + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the AzureAI API call is successful with correct parameters when stream = true', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleAzureAiBody), - stream: true, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleAzureAiBody), + stream: true, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ ...sampleAzureAiBody, stream: true }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ ...sampleAzureAiBody, stream: true }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -715,25 +869,31 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.streamApi({ - body: JSON.stringify({ ...body, stream: false }), - stream: true, - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - ...body, + const response = await connector.streamApi( + { + body: JSON.stringify({ ...body, stream: false }), stream: true, - }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', }, - }); + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...body, + stream: true, + }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, + }, + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -745,7 +905,10 @@ describe('OpenAIConnector', () => { connector.request = mockError; await expect( - connector.streamApi({ body: JSON.stringify(sampleAzureAiBody), stream: true }) + connector.streamApi( + { body: JSON.stringify(sampleAzureAiBody), stream: true }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts index 544b6bf7092c2..6cadc322a3d78 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts @@ -16,6 +16,7 @@ import { ChatCompletionMessageParam, } from 'openai/resources/chat/completions'; import { Stream } from 'openai/streaming'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { removeEndpointFromUrl } from './lib/openai_utils'; import { RunActionParamsSchema, @@ -156,7 +157,11 @@ export class OpenAIConnector extends SubActionConnector { * responsible for making a POST request to the external API endpoint and returning the response data * @param body The stringified request body to be sent in the POST request. */ - public async runApi({ body, signal, timeout }: RunActionParams): Promise { + + public async runApi( + { body, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const sanitizedBody = sanitizeRequest( this.provider, this.url, @@ -164,20 +169,23 @@ export class OpenAIConnector extends SubActionConnector { ...('defaultModel' in this.config ? [this.config.defaultModel] : []) ); const axiosOptions = getAxiosOptions(this.provider, this.key, false); - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: RunActionResponseSchema, - data: sanitizedBody, - signal, - // give up to 2 minutes for response - timeout: timeout ?? DEFAULT_TIMEOUT_MS, - ...axiosOptions, - headers: { - ...this.config.headers, - ...axiosOptions.headers, + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: RunActionResponseSchema, + data: sanitizedBody, + signal, + // give up to 2 minutes for response + timeout: timeout ?? DEFAULT_TIMEOUT_MS, + ...axiosOptions, + headers: { + ...this.config.headers, + ...axiosOptions.headers, + }, }, - }); + connectorUsageCollector + ); return response.data; } @@ -189,12 +197,10 @@ export class OpenAIConnector extends SubActionConnector { * @param body request body for the API request * @param stream flag indicating whether it is a streaming request or not */ - public async streamApi({ - body, - stream, - signal, - timeout, - }: StreamActionParams): Promise { + public async streamApi( + { body, stream, signal, timeout }: StreamActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const executeBody = getRequestWithStreamOption( this.provider, this.url, @@ -205,19 +211,22 @@ export class OpenAIConnector extends SubActionConnector { const axiosOptions = getAxiosOptions(this.provider, this.key, stream); - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: stream ? StreamingResponseSchema : RunActionResponseSchema, - data: executeBody, - signal, - ...axiosOptions, - headers: { - ...this.config.headers, - ...axiosOptions.headers, + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: stream ? StreamingResponseSchema : RunActionResponseSchema, + data: executeBody, + signal, + ...axiosOptions, + headers: { + ...this.config.headers, + ...axiosOptions.headers, + }, + timeout, }, - timeout, - }); + connectorUsageCollector + ); return stream ? pipeStreamingResponse(response) : response.data; } @@ -264,15 +273,21 @@ export class OpenAIConnector extends SubActionConnector { * returned directly to the client for streaming * @param body - the OpenAI Invoke request body */ - public async invokeStream(body: InvokeAIActionParams): Promise { + public async invokeStream( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const { signal, timeout, ...rest } = body; - const res = (await this.streamApi({ - body: JSON.stringify(rest), - stream: true, - signal, - timeout, // do not default if not provided - })) as unknown as IncomingMessage; + const res = (await this.streamApi( + { + body: JSON.stringify(rest), + stream: true, + signal, + timeout, // do not default if not provided + }, + connectorUsageCollector + )) as unknown as IncomingMessage; return res.pipe(new PassThrough()); } @@ -286,7 +301,10 @@ export class OpenAIConnector extends SubActionConnector { * tokenCountStream: Stream; the result for token counting stream * } */ - public async invokeAsyncIterator(body: InvokeAIActionParams): Promise<{ + public async invokeAsyncIterator( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise<{ consumerStream: Stream; tokenCountStream: Stream; }> { @@ -301,6 +319,8 @@ export class OpenAIConnector extends SubActionConnector { rest.model ?? ('defaultModel' in this.config ? this.config.defaultModel : DEFAULT_OPENAI_MODEL), }; + + connectorUsageCollector.addRequestBodyBytes(undefined, requestBody); const stream = await this.openAI.chat.completions.create(requestBody, { signal, timeout, // do not default if not provided @@ -323,9 +343,15 @@ export class OpenAIConnector extends SubActionConnector { * @param body - the OpenAI chat completion request body * @returns an object with the response string and the usage object */ - public async invokeAI(body: InvokeAIActionParams): Promise { + public async invokeAI( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const { signal, timeout, ...rest } = body; - const res = await this.runApi({ body: JSON.stringify(rest), signal, timeout }); + const res = await this.runApi( + { body: JSON.stringify(rest), signal, timeout }, + connectorUsageCollector + ); if (res.choices && res.choices.length > 0 && res.choices[0].message?.content) { const result = res.choices[0].message.content.trim(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts index fb11174e20ba5..821f2b3032661 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts @@ -15,6 +15,7 @@ import { MockedLogger } from '@kbn/logging-mocks'; import { OpsgenieConnectorTypeId } from '../../../common'; import { OpsgenieConnector } from './connector'; import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); @@ -36,6 +37,7 @@ describe('OpsgenieConnector', () => { let mockedActionsConfig: jest.Mocked; let logger: MockedLogger; let services: ReturnType; + let connectorUsageCollector: ConnectorUsageCollector; const defaultCreateAlertExpect = { method: 'post', @@ -75,36 +77,43 @@ describe('OpsgenieConnector', () => { logger, services, }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('calls request with the correct arguments for creating an alert', async () => { - await connector.createAlert({ message: 'hello' }); + await connector.createAlert({ message: 'hello' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ data: { message: 'hello' }, ...ignoredRequestFields, ...defaultCreateAlertExpect, + connectorUsageCollector, }); }); it('calls request without modifying the alias when it is less than 512 characters when creating an alert', async () => { - await connector.createAlert({ message: 'hello', alias: '111' }); + await connector.createAlert({ message: 'hello', alias: '111' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias: '111' }, + connectorUsageCollector, }); }); it('calls request without modifying the alias when it is equal to 512 characters when creating an alert', async () => { const alias = 'a'.repeat(512); - await connector.createAlert({ message: 'hello', alias }); + await connector.createAlert({ message: 'hello', alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias }, + connectorUsageCollector, }); }); @@ -114,12 +123,13 @@ describe('OpsgenieConnector', () => { const hasher = crypto.createHash('sha256'); const sha256Hash = hasher.update(alias); - await connector.createAlert({ message: 'hello', alias }); + await connector.createAlert({ message: 'hello', alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias: `sha-${sha256Hash.digest('hex')}` }, + connectorUsageCollector, }); }); @@ -129,22 +139,24 @@ describe('OpsgenieConnector', () => { const hasher = crypto.createHash('sha256'); const sha256Hash = hasher.update(alias); - await connector.closeAlert({ alias }); + await connector.closeAlert({ alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...createCloseAlertExpect(`sha-${sha256Hash.digest('hex')}`), data: {}, + connectorUsageCollector, }); }); it('calls request with the correct arguments for closing an alert', async () => { - await connector.closeAlert({ user: 'sam', alias: '111' }); + await connector.closeAlert({ user: 'sam', alias: '111' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...createCloseAlertExpect('111'), data: { user: 'sam' }, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts index cd86a8ac7542a..0963ac720c80a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts @@ -9,6 +9,7 @@ import crypto from 'crypto'; import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import { AxiosError } from 'axios'; import { isEmpty } from 'lodash'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { OpsgenieSubActions } from '../../../common'; import { CreateAlertParamsSchema, CloseAlertParamsSchema, Response } from './schema'; import { CloseAlertParams, Config, CreateAlertParams, FailureResponseType, Secrets } from './types'; @@ -67,14 +68,20 @@ export class OpsgenieConnector extends SubActionConnector { } } - public async createAlert(params: CreateAlertParams) { - const res = await this.request({ - method: 'post', - url: this.concatPathToURL('v2/alerts').toString(), - data: { ...params, ...OpsgenieConnector.createAliasObj(params.alias) }, - headers: this.createHeaders(), - responseSchema: Response, - }); + public async createAlert( + params: CreateAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + method: 'post', + url: this.concatPathToURL('v2/alerts').toString(), + data: { ...params, ...OpsgenieConnector.createAliasObj(params.alias) }, + headers: this.createHeaders(), + responseSchema: Response, + }, + connectorUsageCollector + ); return res.data; } @@ -107,7 +114,10 @@ export class OpsgenieConnector extends SubActionConnector { return { Authorization: `GenieKey ${this.secrets.apiKey}` }; } - public async closeAlert(params: CloseAlertParams) { + public async closeAlert( + params: CloseAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { const newAlias = OpsgenieConnector.createAlias(params.alias); const fullURL = this.concatPathToURL(`v2/alerts/${newAlias}/close`); @@ -115,13 +125,16 @@ export class OpsgenieConnector extends SubActionConnector { const { alias, ...paramsWithoutAlias } = params; - const res = await this.request({ - method: 'post', - url: fullURL.toString(), - data: paramsWithoutAlias, - headers: this.createHeaders(), - responseSchema: Response, - }); + const res = await this.request( + { + method: 'post', + url: fullURL.toString(), + data: paramsWithoutAlias, + headers: this.createHeaders(), + responseSchema: Response, + }, + connectorUsageCollector + ); return res.data; } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts index 86cdca4740f6d..38446eefe44f1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts @@ -10,7 +10,7 @@ import moment from 'moment'; jest.mock('./post_pagerduty', () => ({ postPagerduty: jest.fn(), })); -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateSecrets, validateParams } from '@kbn/actions-plugin/server/lib'; import { postPagerduty } from './post_pagerduty'; import { Logger } from '@kbn/core/server'; @@ -31,10 +31,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: PagerDutyConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('get()', () => { @@ -269,6 +274,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -350,6 +356,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -458,6 +465,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -535,6 +543,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -578,6 +587,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -608,6 +618,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -638,6 +649,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -668,6 +680,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -708,6 +721,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -771,6 +785,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -837,6 +852,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -902,6 +918,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts index cfd11d6803df8..c4d2444540cad 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts @@ -198,8 +198,16 @@ function getPagerDutyApiUrl(config: ConnectorTypeConfigType): string { async function executor( execOptions: PagerDutyConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, secrets, params, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + secrets, + params, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const apiUrl = getPagerDutyApiUrl(config); const headers = { @@ -213,7 +221,8 @@ async function executor( response = await postPagerduty( { apiUrl, data, headers, services }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.pagerduty.postingErrorMessage', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts index 0ef41637967d2..8b0937f9d857b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts @@ -7,7 +7,7 @@ import axios, { AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; @@ -22,7 +22,8 @@ interface PostPagerdutyOptions { export async function postPagerduty( options: PostPagerdutyOptions, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { apiUrl, data, headers } = options; const axiosInstance = axios.create(); @@ -36,5 +37,6 @@ export async function postPagerduty( headers, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts index 4e031bdaafeea..6f3999dc70df7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts @@ -13,6 +13,7 @@ import { ResilientConnector } from './resilient'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { RESILIENT_CONNECTOR_ID } from './constants'; import { PushToServiceIncidentSchema } from './schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { @@ -83,13 +84,15 @@ const mockIncidentUpdate = (withUpdateError = false) => { }) ); }; +let connectorUsageCollector: ConnectorUsageCollector; describe('IBM Resilient connector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new ResilientConnector( { connector: { id: '1', type: RESILIENT_CONNECTOR_ID }, configurationUtilities: actionsConfigMock.create(), - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), config: { orgId, apiUrl }, secrets: { apiKeyId, apiKeySecret }, @@ -107,6 +110,10 @@ describe('IBM Resilient connector', () => { beforeEach(() => { jest.resetAllMocks(); jest.setSystemTime(TIMESTAMP); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('getIncident', () => { @@ -129,12 +136,12 @@ describe('IBM Resilient connector', () => { }); it('returns the incident correctly', async () => { - const res = await connector.getIncident({ id: '1' }); + const res = await connector.getIncident({ id: '1' }, connectorUsageCollector); expect(res).toEqual(incidentMock); }); it('should call request with correct arguments', async () => { - await connector.getIncident({ id: '1' }); + await connector.getIncident({ id: '1' }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, method: 'GET', @@ -147,6 +154,7 @@ describe('IBM Resilient connector', () => { params: { text_content_output_format: 'objects_convert', }, + connectorUsageCollector, }); }); @@ -154,7 +162,7 @@ describe('IBM Resilient connector', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - await expect(connector.getIncident({ id: '1' })).rejects.toThrow( + await expect(connector.getIncident({ id: '1' }, connectorUsageCollector)).rejects.toThrow( 'Unable to get incident with id 1. Error: An error has occurred' ); }); @@ -183,7 +191,7 @@ describe('IBM Resilient connector', () => { }); it('creates the incident correctly', async () => { - const res = await connector.createIncident(incidentMock); + const res = await connector.createIncident(incidentMock, connectorUsageCollector); expect(res).toEqual({ title: '1', @@ -194,7 +202,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.createIncident(incidentMock); + await connector.createIncident(incidentMock, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -214,6 +222,7 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); @@ -223,12 +232,15 @@ describe('IBM Resilient connector', () => { }); await expect( - connector.createIncident({ - name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 6, - }) + connector.createIncident( + { + name: 'title', + description: 'desc', + incidentTypes: [1001], + severityCode: 6, + }, + connectorUsageCollector + ) ).rejects.toThrow( '[Action][IBM Resilient]: Unable to create incident. Error: An error has occurred' ); @@ -237,7 +249,7 @@ describe('IBM Resilient connector', () => { it('should throw if the required attributes are not received in response', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); - await expect(connector.createIncident(incidentMock)).rejects.toThrow( + await expect(connector.createIncident(incidentMock, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to create incident. Error: Response validation failed (Error: [id]: expected value of type [number] but got [undefined]).' ); }); @@ -255,7 +267,7 @@ describe('IBM Resilient connector', () => { }; it('updates the incident correctly', async () => { mockIncidentUpdate(); - const res = await connector.updateIncident(req); + const res = await connector.updateIncident(req, connectorUsageCollector); expect(res).toEqual({ title: '1', @@ -268,15 +280,18 @@ describe('IBM Resilient connector', () => { it('should call request with correct arguments', async () => { mockIncidentUpdate(); - await connector.updateIncident({ - incidentId: '1', - incident: { - name: 'title_updated', - description: 'desc_updated', - incidentTypes: [1001], - severityCode: 5, + await connector.updateIncident( + { + incidentId: '1', + incident: { + name: 'title_updated', + description: 'desc_updated', + incidentTypes: [1001], + severityCode: 5, + }, }, - }); + connectorUsageCollector + ); expect(requestMock.mock.calls[1][0]).toEqual({ ...ignoredRequestFields, @@ -332,13 +347,14 @@ describe('IBM Resilient connector', () => { }, ], }, + connectorUsageCollector, }); }); it('it should throw an error', async () => { mockIncidentUpdate(true); - await expect(connector.updateIncident(req)).rejects.toThrow( + await expect(connector.updateIncident(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to update incident with id 1. Error: An error has occurred' ); }); @@ -361,7 +377,7 @@ describe('IBM Resilient connector', () => { ); requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); - await expect(connector.updateIncident(req)).rejects.toThrow( + await expect(connector.updateIncident(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to update incident with id 1. Error: Response validation failed (Error: [success]: expected value of type [boolean] but got [undefined]).' ); }); @@ -388,7 +404,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.addComment(req); + await connector.addComment(req, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -404,6 +420,7 @@ describe('IBM Resilient connector', () => { format: 'text', }, }, + connectorUsageCollector, }); }); @@ -412,7 +429,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.addComment(req)).rejects.toThrow( + await expect(connector.addComment(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to create comment at incident with id 1. Error: An error has occurred.' ); }); @@ -428,7 +445,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.getIncidentTypes(); + await connector.getIncidentTypes(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -439,11 +456,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns incident types correctly', async () => { - const res = await connector.getIncidentTypes(); + const res = await connector.getIncidentTypes(undefined, connectorUsageCollector); expect(res).toEqual([ { id: '17', name: 'Communication error (fax; email)' }, @@ -456,7 +474,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.getIncidentTypes()).rejects.toThrow( + await expect(connector.getIncidentTypes(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' ); }); @@ -466,7 +484,7 @@ describe('IBM Resilient connector', () => { createAxiosResponse({ data: { id: '1001', name: 'Custom type' } }) ); - await expect(connector.getIncidentTypes()).rejects.toThrow( + await expect(connector.getIncidentTypes(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: Response validation failed (Error: [values]: expected value of type [array] but got [undefined]).' ); }); @@ -484,7 +502,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.getSeverity(); + await connector.getSeverity(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -495,11 +513,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns severity correctly', async () => { - const res = await connector.getSeverity(); + const res = await connector.getSeverity(undefined, connectorUsageCollector); expect(res).toEqual([ { @@ -522,7 +541,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.getSeverity()).rejects.toThrow( + await expect(connector.getSeverity(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get severity. Error: An error has occurred.' ); }); @@ -532,7 +551,7 @@ describe('IBM Resilient connector', () => { createAxiosResponse({ data: { id: '10', name: 'Critical' } }) ); - await expect(connector.getSeverity()).rejects.toThrow( + await expect(connector.getSeverity(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get severity. Error: Response validation failed (Error: [values]: expected value of type [array] but got [undefined]).' ); }); @@ -547,7 +566,7 @@ describe('IBM Resilient connector', () => { ); }); it('should call request with correct arguments', async () => { - await connector.getFields(); + await connector.getFields(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ @@ -559,11 +578,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns common fields correctly', async () => { - const res = await connector.getFields(); + const res = await connector.getFields(undefined, connectorUsageCollector); expect(res).toEqual(resilientFields); }); @@ -571,7 +591,7 @@ describe('IBM Resilient connector', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - await expect(connector.getFields()).rejects.toThrow( + await expect(connector.getFields(undefined, connectorUsageCollector)).rejects.toThrow( 'Unable to get fields. Error: An error has occurred' ); }); @@ -579,7 +599,7 @@ describe('IBM Resilient connector', () => { it('should throw if the required attributes are not received in response', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { someField: 'test' } })); - await expect(connector.getFields()).rejects.toThrow( + await expect(connector.getFields(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get fields. Error: Response validation failed (Error: expected value of type [array] but got [Object]).' ); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts index 1351488dbf892..da297369ae024 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts @@ -10,6 +10,7 @@ import { omitBy, isNil } from 'lodash/fp'; import { CaseConnector, getBasicAuthHeader, ServiceParams } from '@kbn/actions-plugin/server'; import { schema, Type } from '@kbn/config-schema'; import { getErrorMessage } from '@kbn/actions-plugin/server/lib/axios_utils'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { CreateIncidentData, ExternalServiceIncidentResponse, @@ -117,7 +118,10 @@ export class ResilientConnector extends CaseConnector< return `${urlWithoutTrailingSlash}/${VIEW_INCIDENT_URL}/${key}`; } - public async createIncident(incident: Incident): Promise { + public async createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { let data: CreateIncidentData = { name: incident.name, @@ -150,19 +154,22 @@ export class ResilientConnector extends CaseConnector< }; } - const res = await this.request({ - url: `${this.urls.incident}?text_content_output_format=objects_convert`, - method: 'POST', - data, - headers: this.getAuthHeaders(), - responseSchema: schema.object( - { - id: schema.number(), - create_date: schema.number(), - }, - { unknowns: 'allow' } - ), - }); + const res = await this.request( + { + url: `${this.urls.incident}?text_content_output_format=objects_convert`, + method: 'POST', + data, + headers: this.getAuthHeaders(), + responseSchema: schema.object( + { + id: schema.number(), + create_date: schema.number(), + }, + { unknowns: 'allow' } + ), + }, + connectorUsageCollector + ); const { id, create_date: createDate } = res.data; @@ -179,30 +186,33 @@ export class ResilientConnector extends CaseConnector< } } - public async updateIncident({ - incidentId, - incident, - }: UpdateIncidentParams): Promise { + public async updateIncident( + { incidentId, incident }: UpdateIncidentParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const latestIncident = await this.getIncident({ id: incidentId }); + const latestIncident = await this.getIncident({ id: incidentId }, connectorUsageCollector); // Remove null or undefined values. Allowing null values sets the field in IBM Resilient to empty. const newIncident = omitBy(isNil, incident); const data = formatUpdateRequest({ oldIncident: latestIncident, newIncident }); - const res = await this.request({ - method: 'PATCH', - url: `${this.urls.incident}/${incidentId}`, - data, - headers: this.getAuthHeaders(), - responseSchema: schema.object({ success: schema.boolean() }, { unknowns: 'allow' }), - }); + const res = await this.request( + { + method: 'PATCH', + url: `${this.urls.incident}/${incidentId}`, + data, + headers: this.getAuthHeaders(), + responseSchema: schema.object({ success: schema.boolean() }, { unknowns: 'allow' }), + }, + connectorUsageCollector + ); if (!res.data.success) { throw new Error('Error while updating incident'); } - const updatedIncident = await this.getIncident({ id: incidentId }); + const updatedIncident = await this.getIncident({ id: incidentId }, connectorUsageCollector); return { title: `${updatedIncident.id}`, @@ -220,15 +230,21 @@ export class ResilientConnector extends CaseConnector< } } - public async addComment({ incidentId, comment }: { incidentId: string; comment: string }) { + public async addComment( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { try { - await this.request({ - method: 'POST', - url: this.urls.comment.replace('{inc_id}', incidentId), - data: { text: { format: 'text', content: comment } }, - headers: this.getAuthHeaders(), - responseSchema: schema.object({}, { unknowns: 'allow' }), - }); + await this.request( + { + method: 'POST', + url: this.urls.comment.replace('{inc_id}', incidentId), + data: { text: { format: 'text', content: comment } }, + headers: this.getAuthHeaders(), + responseSchema: schema.object({}, { unknowns: 'allow' }), + }, + connectorUsageCollector + ); } catch (error) { throw new Error( getErrorMessage( @@ -239,17 +255,23 @@ export class ResilientConnector extends CaseConnector< } } - public async getIncident({ id }: { id: string }): Promise { + public async getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: `${this.urls.incident}/${id}`, - params: { - text_content_output_format: 'objects_convert', + const res = await this.request( + { + method: 'GET', + url: `${this.urls.incident}/${id}`, + params: { + text_content_output_format: 'objects_convert', + }, + headers: this.getAuthHeaders(), + responseSchema: GetIncidentResponseSchema, }, - headers: this.getAuthHeaders(), - responseSchema: GetIncidentResponseSchema, - }); + connectorUsageCollector + ); return res.data; } catch (error) { @@ -259,14 +281,20 @@ export class ResilientConnector extends CaseConnector< } } - public async getIncidentTypes(): Promise { + public async getIncidentTypes( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: this.urls.incidentTypes, - headers: this.getAuthHeaders(), - responseSchema: GetIncidentTypesResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.urls.incidentTypes, + headers: this.getAuthHeaders(), + responseSchema: GetIncidentTypesResponseSchema, + }, + connectorUsageCollector + ); const incidentTypes = res.data?.values ?? []; @@ -281,14 +309,20 @@ export class ResilientConnector extends CaseConnector< } } - public async getSeverity(): Promise { + public async getSeverity( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: this.urls.severity, - headers: this.getAuthHeaders(), - responseSchema: GetSeverityResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.urls.severity, + headers: this.getAuthHeaders(), + responseSchema: GetSeverityResponseSchema, + }, + connectorUsageCollector + ); const severities = res.data?.values ?? []; return severities.map((type: { value: number; label: string }) => ({ @@ -302,14 +336,17 @@ export class ResilientConnector extends CaseConnector< } } - public async getFields() { + public async getFields(params: unknown, connectorUsageCollector: ConnectorUsageCollector) { try { - const res = await this.request({ - method: 'GET', - url: this.getIncidentFieldsUrl(), - headers: this.getAuthHeaders(), - responseSchema: GetCommonFieldsResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.getIncidentFieldsUrl(), + headers: this.getAuthHeaders(), + responseSchema: GetCommonFieldsResponseSchema, + }, + connectorUsageCollector + ); const fields = res.data.map((field) => { return { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts index ced2784f057a6..8a13a48e47be1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts @@ -13,12 +13,20 @@ import { } from '../../../common/sentinelone/types'; import { API_PATH } from './sentinelone'; import { SentinelOneGetActivitiesResponseSchema } from '../../../common/sentinelone/schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; describe('SentinelOne Connector', () => { let connectorInstance: ReturnType; + let connectorUsageCollector: ConnectorUsageCollector; + const logger = loggingSystemMock.createLogger(); beforeEach(() => { connectorInstance = sentinelOneConnectorMocks.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('#fetchAgentFiles()', () => { @@ -35,15 +43,17 @@ describe('SentinelOne Connector', () => { it('should error if no agent id provided', async () => { fetchAgentFilesParams.agentId = ''; - await expect(connectorInstance.fetchAgentFiles(fetchAgentFilesParams)).rejects.toHaveProperty( - 'message', - "'agentId' parameter is required" - ); + await expect( + connectorInstance.fetchAgentFiles(fetchAgentFilesParams, connectorUsageCollector) + ).rejects.toHaveProperty('message', "'agentId' parameter is required"); }); it('should call SentinelOne fetch-files API with expected data', async () => { const fetchFilesUrl = `${connectorInstance.constructorParams.config.url}${API_PATH}/agents/${fetchAgentFilesParams.agentId}/actions/fetch-files`; - const response = await connectorInstance.fetchAgentFiles(fetchAgentFilesParams); + const response = await connectorInstance.fetchAgentFiles( + fetchAgentFilesParams, + connectorUsageCollector + ); expect(response).toEqual({ data: { success: true }, errors: null }); expect(connectorInstance.requestSpy).toHaveBeenLastCalledWith({ @@ -76,14 +86,14 @@ describe('SentinelOne Connector', () => { it('should error if called with invalid agent id', async () => { downloadAgentFileParams.agentId = ''; await expect( - connectorInstance.downloadAgentFile(downloadAgentFileParams) + connectorInstance.downloadAgentFile(downloadAgentFileParams, connectorUsageCollector) ).rejects.toHaveProperty('message', "'agentId' parameter is required"); }); it('should call SentinelOne api with expected url', async () => { - await expect(connectorInstance.downloadAgentFile(downloadAgentFileParams)).resolves.toEqual( - connectorInstance.mockResponses.downloadAgentFileApiResponse - ); + await expect( + connectorInstance.downloadAgentFile(downloadAgentFileParams, connectorUsageCollector) + ).resolves.toEqual(connectorInstance.mockResponses.downloadAgentFileApiResponse); }); }); @@ -122,7 +132,10 @@ describe('SentinelOne Connector', () => { describe('#downloadRemoteScriptResults()', () => { it('should call SentinelOne api to retrieve task results', async () => { - await connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }); + await connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ); expect(connectorInstance.requestSpy).toHaveBeenCalledWith( expect.objectContaining({ @@ -136,13 +149,19 @@ describe('SentinelOne Connector', () => { connectorInstance.mockResponses.getRemoteScriptResults.data.download_links = []; await expect( - connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }) + connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ) ).rejects.toThrow('Download URL for script results of task id [task-123] not found'); }); it('should return a Stream for downloading the file', async () => { await expect( - connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }) + connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ) ).resolves.toEqual(connectorInstance.mockResponses.downloadRemoteScriptResults); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts index 99f486b44a087..dd73bafae8d2f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts @@ -8,6 +8,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { Stream } from 'stream'; import type { SentinelOneConfig, @@ -157,67 +158,94 @@ export class SentinelOneConnector extends SubActionConnector< }); } - public async fetchAgentFiles({ files, agentId, zipPassCode }: SentinelOneFetchAgentFilesParams) { + public async fetchAgentFiles( + { files, agentId, zipPassCode }: SentinelOneFetchAgentFilesParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!agentId) { throw new Error(`'agentId' parameter is required`); } - return this.sentinelOneApiRequest({ - url: `${this.urls.agents}/${agentId}/actions/fetch-files`, - method: 'post', - data: { + return this.sentinelOneApiRequest( + { + url: `${this.urls.agents}/${agentId}/actions/fetch-files`, + method: 'post', data: { - password: zipPassCode, - files, + data: { + password: zipPassCode, + files, + }, }, + responseSchema: SentinelOneFetchAgentFilesResponseSchema, }, - responseSchema: SentinelOneFetchAgentFilesResponseSchema, - }); + connectorUsageCollector + ); } - public async downloadAgentFile({ agentId, activityId }: SentinelOneDownloadAgentFileParams) { + public async downloadAgentFile( + { agentId, activityId }: SentinelOneDownloadAgentFileParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!agentId) { throw new Error(`'agentId' parameter is required`); } - return this.sentinelOneApiRequest({ - url: `${this.urls.agents}/${agentId}/uploads/${activityId}`, - method: 'get', - responseType: 'stream', - responseSchema: SentinelOneDownloadAgentFileResponseSchema, - }); + return this.sentinelOneApiRequest( + { + url: `${this.urls.agents}/${agentId}/uploads/${activityId}`, + method: 'get', + responseType: 'stream', + responseSchema: SentinelOneDownloadAgentFileResponseSchema, + }, + connectorUsageCollector + ); } - public async getActivities(queryParams?: SentinelOneGetActivitiesParams) { - return this.sentinelOneApiRequest({ - url: this.urls.activities, - method: 'get', - params: queryParams, - responseSchema: SentinelOneGetActivitiesResponseSchema, - }); + public async getActivities( + queryParams?: SentinelOneGetActivitiesParams, + connectorUsageCollector?: ConnectorUsageCollector + ) { + return this.sentinelOneApiRequest( + { + url: this.urls.activities, + method: 'get', + params: queryParams, + responseSchema: SentinelOneGetActivitiesResponseSchema, + }, + connectorUsageCollector! + ); } - public async executeScript({ filter, script }: SentinelOneExecuteScriptParams) { + public async executeScript( + { filter, script }: SentinelOneExecuteScriptParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!filter.ids && !filter.uuids) { throw new Error(`A filter must be defined; either 'ids' or 'uuids'`); } - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptsExecute, - method: 'post', - data: { + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptsExecute, + method: 'post', data: { - outputDestination: 'SentinelCloud', - ...script, + data: { + outputDestination: 'SentinelCloud', + ...script, + }, + filter, }, - filter, + responseSchema: SentinelOneExecuteScriptResponseSchema, }, - responseSchema: SentinelOneExecuteScriptResponseSchema, - }); + connectorUsageCollector + ); } - public async isolateHost({ alertIds, ...payload }: SentinelOneIsolateHostParams) { - const response = await this.getAgents(payload); + public async isolateHost( + { alertIds, ...payload }: SentinelOneIsolateHostParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const response = await this.getAgents(payload, connectorUsageCollector); if (response.data.length === 0) { const errorMessage = 'No agents found'; @@ -233,20 +261,26 @@ export class SentinelOneConnector extends SubActionConnector< const agentId = response.data[0].id; - return this.sentinelOneApiRequest({ - url: this.urls.isolateHost, - method: 'post', - data: { - filter: { - ids: agentId, + return this.sentinelOneApiRequest( + { + url: this.urls.isolateHost, + method: 'post', + data: { + filter: { + ids: agentId, + }, }, + responseSchema: SentinelOneIsolateHostResponseSchema, }, - responseSchema: SentinelOneIsolateHostResponseSchema, - }); + connectorUsageCollector + ); } - public async releaseHost({ alertIds, ...payload }: SentinelOneIsolateHostParams) { - const response = await this.getAgents(payload); + public async releaseHost( + { alertIds, ...payload }: SentinelOneIsolateHostParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const response = await this.getAgents(payload, connectorUsageCollector); if (response.data.length === 0) { throw new Error('No agents found'); @@ -258,57 +292,76 @@ export class SentinelOneConnector extends SubActionConnector< const agentId = response.data[0].id; - return this.sentinelOneApiRequest({ - url: this.urls.releaseHost, - method: 'post', - data: { - filter: { - ids: agentId, + return this.sentinelOneApiRequest( + { + url: this.urls.releaseHost, + method: 'post', + data: { + filter: { + ids: agentId, + }, }, + responseSchema: SentinelOneIsolateHostResponseSchema, }, - responseSchema: SentinelOneIsolateHostResponseSchema, - }); + connectorUsageCollector + ); } public async getAgents( - payload: SentinelOneGetAgentsParams + payload: SentinelOneGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.agents, - params: { - ...payload, + return this.sentinelOneApiRequest( + { + url: this.urls.agents, + params: { + ...payload, + }, + responseSchema: SentinelOneGetAgentsResponseSchema, }, - responseSchema: SentinelOneGetAgentsResponseSchema, - }); + connectorUsageCollector + ); } public async getRemoteScriptStatus( - payload: SentinelOneGetRemoteScriptStatusParams + payload: SentinelOneGetRemoteScriptStatusParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptStatus, - params: { - parent_task_id: payload.parentTaskId, + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptStatus, + params: { + parent_task_id: payload.parentTaskId, + }, + responseSchema: SentinelOneGetRemoteScriptStatusResponseSchema, }, - responseSchema: SentinelOneGetRemoteScriptStatusResponseSchema, - }) as unknown as SentinelOneGetRemoteScriptStatusApiResponse; + connectorUsageCollector + ) as unknown as SentinelOneGetRemoteScriptStatusApiResponse; } - public async getRemoteScriptResults({ - taskIds, - }: SentinelOneGetRemoteScriptResultsParams): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptsResults, - method: 'post', - data: { data: { taskIds } }, - responseSchema: SentinelOneGetRemoteScriptResultsResponseSchema, - }) as unknown as SentinelOneGetRemoteScriptResultsApiResponse; + public async getRemoteScriptResults( + { taskIds }: SentinelOneGetRemoteScriptResultsParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptsResults, + method: 'post', + data: { data: { taskIds } }, + responseSchema: SentinelOneGetRemoteScriptResultsResponseSchema, + }, + connectorUsageCollector + ) as unknown as SentinelOneGetRemoteScriptResultsApiResponse; } - public async downloadRemoteScriptResults({ - taskId, - }: SentinelOneDownloadRemoteScriptResultsParams): Promise { - const scriptResultsInfo = await this.getRemoteScriptResults({ taskIds: [taskId] }); + public async downloadRemoteScriptResults( + { taskId }: SentinelOneDownloadRemoteScriptResultsParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const scriptResultsInfo = await this.getRemoteScriptResults( + { taskIds: [taskId] }, + connectorUsageCollector + ); this.logger.debug( () => `script results for taskId [${taskId}]:\n${JSON.stringify(scriptResultsInfo)}` @@ -327,26 +380,33 @@ export class SentinelOneConnector extends SubActionConnector< throw new Error(`Download URL for script results of task id [${taskId}] not found`); } - const downloadConnection = await this.request({ - url: fileUrl, - method: 'get', - responseType: 'stream', - responseSchema: SentinelOneDownloadRemoteScriptResultsResponseSchema, - }); + const downloadConnection = await this.request( + { + url: fileUrl, + method: 'get', + responseType: 'stream', + responseSchema: SentinelOneDownloadRemoteScriptResultsResponseSchema, + }, + connectorUsageCollector + ); return downloadConnection.data; } private async sentinelOneApiRequest( - req: SubActionRequestParams + req: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request({ - ...req, - params: { - ...req.params, - APIToken: this.secrets.token, + const response = await this.request( + { + ...req, + params: { + ...req.params, + APIToken: this.secrets.token, + }, }, - }); + connectorUsageCollector + ); return response.data; } @@ -374,15 +434,19 @@ export class SentinelOneConnector extends SubActionConnector< } public async getRemoteScripts( - payload: SentinelOneGetRemoteScriptsParams + payload: SentinelOneGetRemoteScriptsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScripts, - params: { - limit: API_MAX_RESULTS, - ...payload, + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScripts, + params: { + limit: API_MAX_RESULTS, + ...payload, + }, + responseSchema: SentinelOneGetRemoteScriptsResponseSchema, }, - responseSchema: SentinelOneGetRemoteScriptsResponseSchema, - }); + connectorUsageCollector + ); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts index 082098023fc3f..29fd5d41adc26 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts @@ -6,6 +6,7 @@ */ import { validateParams } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { Logger } from '@kbn/core/server'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { getConnectorType, ServerLogConnectorType, ServerLogConnectorTypeExecutorOptions } from '.'; @@ -107,6 +108,10 @@ describe('execute()', () => { secrets: {}, configurationUtilities, logger: mockedLogger, + connectorUsageCollector: new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }), }; await connectorType.executor(executorOptions); expect(mockedLogger.info).toHaveBeenCalledWith('Server log: message text here'); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts index bbfaf902ba671..d32f52cd698ee 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts @@ -102,7 +102,15 @@ async function executorITOM( ExecutorParamsITOM > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = execOptions.services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -119,6 +127,7 @@ async function executorITOM( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts index 01d8ed53478ca..951c2731b526d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { snExternalServiceConfig } from '../lib/servicenow/config'; import { itomEventParams, serviceNowChoices } from '../lib/servicenow/mocks'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -33,8 +34,13 @@ const configurationUtilities = actionsConfigMock.create(); describe('ServiceNow SIR service', () => { let service: ExternalServiceITOM; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { config: { apiUrl: 'https://example.com/', isOAuth: false }, @@ -44,6 +50,7 @@ describe('ServiceNow SIR service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-itom'], axiosInstance: axios, + connectorUsageCollector, }) as ExternalServiceITOM; }); @@ -69,6 +76,7 @@ describe('ServiceNow SIR service', () => { url: 'https://example.com/api/global/em/jsonv2', method: 'post', data: { records: [itomEventParams] }, + connectorUsageCollector, }); }); }); @@ -85,6 +93,7 @@ describe('ServiceNow SIR service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=em_event^element=severity^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts index e096b67de7ef4..a6ed020461194 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts @@ -23,6 +23,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalServiceITOM => { const snService = createExternalServiceCommon({ credentials, @@ -30,6 +31,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); const addEvent = async (params: ExecutorSubActionAddEventParams) => { @@ -41,6 +43,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data: { records: [params] }, configurationUtilities, + connectorUsageCollector, }); snService.checkInstance(res); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts index 0322b0e341844..6ab6bc389ac7a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts @@ -125,8 +125,16 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + params, + secrets, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -143,6 +151,7 @@ async function executor( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts index 1c068dc60489d..5590da4cbfbd6 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { serviceNowCommonFields, serviceNowChoices } from '../lib/servicenow/mocks'; import { snExternalServiceConfig } from '../lib/servicenow/config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios', () => ({ @@ -122,6 +123,7 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -135,6 +137,7 @@ const expectImportedIncident = (update: boolean) => { u_description: 'desc', ...(update ? { elastic_incident_id: '1' } : {}), }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -143,14 +146,20 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; describe('ServiceNow service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { // The trailing slash at the end of the url is intended. @@ -162,6 +171,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }); }); @@ -177,6 +187,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -217,6 +228,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -381,6 +393,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -408,6 +421,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -421,6 +435,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -434,6 +449,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -487,6 +503,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await createIncident(service); @@ -497,6 +514,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -506,6 +524,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -514,6 +533,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -572,6 +592,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -596,6 +617,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -609,6 +631,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -624,6 +647,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -660,6 +684,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await updateIncident(service); @@ -669,6 +694,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -678,6 +704,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', elastic_incident_id: '1' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -686,6 +713,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -747,6 +775,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -772,6 +801,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -785,6 +815,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -801,6 +832,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -820,6 +852,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -841,6 +874,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -853,6 +887,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=sn_si_incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -889,6 +924,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -910,6 +946,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -923,6 +960,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=sn_si_incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1015,6 +1053,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); await service.checkIfApplicationIsInstalled(); expect(requestMock).not.toHaveBeenCalled(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts index d564d6bc79d62..8d842c6e6fccf 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts @@ -116,8 +116,16 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + params, + secrets, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -134,6 +142,7 @@ async function executor( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts index 97a0570eb50db..91eb7e4dcd7af 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { observables } from '../lib/servicenow/mocks'; import { snExternalServiceConfig } from '../lib/servicenow/config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -31,6 +32,7 @@ jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { axios.create = jest.fn(() => axios); const requestMock = utils.request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; const mockApplicationVersion = () => requestMock.mockImplementationOnce(() => ({ @@ -70,6 +72,7 @@ const expectAddObservables = (single: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); const url = single @@ -85,6 +88,7 @@ const expectAddObservables = (single: boolean) => { url, method: 'post', data, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; @@ -92,6 +96,10 @@ describe('ServiceNow SIR service', () => { let service: ExternalServiceSIR; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { config: { apiUrl: 'https://example.com/', isOAuth: false }, @@ -101,6 +109,7 @@ describe('ServiceNow SIR service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }) as ExternalServiceSIR; }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts index 69836a5b95e29..8fc7249c1d6a1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts @@ -28,6 +28,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalServiceSIR => { const snService = createExternalServiceCommon({ credentials, @@ -35,6 +36,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); const _addObservable = async (data: Observable | Observable[], url: string) => { @@ -47,6 +49,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data, configurationUtilities, + connectorUsageCollector, }); snService.checkInstance(res); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts index 3f6203b725913..7d897ce5a3b77 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts @@ -9,6 +9,7 @@ import { Logger } from '@kbn/core/server'; import { Services, ActionTypeExecutorResult as ConnectorTypeExecutorResult, + ConnectorUsageCollector, } from '@kbn/actions-plugin/server/types'; import { validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { @@ -35,6 +36,7 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: SlackConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); @@ -43,6 +45,10 @@ beforeEach(() => { return { status: 'ok', actionId: options.actionId }; }, }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -181,6 +187,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(response).toMatchInlineSnapshot(` Object { @@ -201,6 +208,7 @@ describe('execute()', () => { params: { message: 'failure: this invocation should fail' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"slack mockExecutor failure: this invocation should fail"` @@ -226,6 +234,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -252,6 +261,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -278,6 +288,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -304,6 +315,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -330,6 +342,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts index 98573f98f2aa8..489d7c22b0286 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts @@ -139,7 +139,8 @@ function validateConnectorTypeConfig( async function slackExecutor( execOptions: SlackConnectorTypeExecutorOptions ): Promise> { - const { actionId, secrets, params, configurationUtilities, logger } = execOptions; + const { actionId, secrets, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; let result: IncomingWebhookResult; const { webhookUrl } = secrets; @@ -163,6 +164,7 @@ async function slackExecutor( const webhook = new IncomingWebhook(webhookUrl, { agent, }); + connectorUsageCollector.addRequestBodyBytes(undefined, { text: message }); result = await webhook.send(message); } catch (err) { if (err.original == null || err.original.response == null) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts index 59030a71aaa05..84e5b68a41c7e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts @@ -7,7 +7,7 @@ import axios from 'axios'; import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { getConnectorType } from '.'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; @@ -39,10 +39,15 @@ const headers = { let connectorType: SlackApiConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -198,6 +203,7 @@ describe('execute', () => { params: {} as PostMessageParams, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"[Action][ExternalService] -> [Slack API] Unsupported subAction type undefined."` @@ -296,6 +302,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -306,6 +313,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', text: 'some text' }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -386,6 +394,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -396,6 +405,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'LKJHGF345', text: 'some text' }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -476,6 +486,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -486,6 +497,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'LKJHGF345', blocks: testBlock.blocks }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -525,6 +537,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -534,6 +547,7 @@ describe('execute', () => { logger: mockedLogger, method: 'get', url: 'https://slack.com/api/conversations.info?channel=ZXCVBNM567', + connectorUsageCollector, }); expect(response).toEqual({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts index 35e85e98e6645..b816a1b014678 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts @@ -107,6 +107,7 @@ const slackApiExecutor = async ({ secrets, configurationUtilities, logger, + connectorUsageCollector, }: SlackApiExecutorOptions): Promise> => { const subAction = params.subAction; @@ -128,7 +129,8 @@ const slackApiExecutor = async ({ secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (subAction === 'validChannelId') { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts index 1389d4a98e9ec..936d4006006d1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts @@ -13,6 +13,7 @@ import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.moc import { createExternalService } from './service'; import { SlackApiService } from '../../../common/slack_api/types'; import { SLACK_API_CONNECTOR_ID } from '../../../common/slack_api/constants'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -28,6 +29,7 @@ jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { axios.create = jest.fn(() => axios); const requestMock = request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; const channel = { id: 'channel_id_1', @@ -117,12 +119,17 @@ describe('Slack API service', () => { let service: SlackApiService; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { secrets: { token: 'token' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -138,7 +145,8 @@ describe('Slack API service', () => { secrets: { token: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrowErrorMatchingInlineSnapshot(`"[Action][Slack API]: Wrong configuration."`); }); @@ -172,6 +180,7 @@ describe('Slack API service', () => { configurationUtilities, method: 'get', url: 'https://slack.com/api/conversations.info?channel=channel_id_1', + connectorUsageCollector, }); }); @@ -207,6 +216,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', text: 'a message' }, + connectorUsageCollector, }); }); @@ -231,6 +241,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', text: 'a message' }, + connectorUsageCollector, }); }); @@ -251,6 +262,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', text: 'a message' }, + connectorUsageCollector, }); }); @@ -291,6 +303,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); @@ -315,6 +328,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); @@ -338,6 +352,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts index 28e9ee8be4b5d..7180b0982d92c 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts @@ -13,6 +13,7 @@ import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; import type { ActionTypeExecutorResult as ConnectorTypeExecutorResult } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SLACK_CONNECTOR_NAME } from './translations'; import type { PostMessageSubActionParams, @@ -111,7 +112,8 @@ export const createExternalService = ( secrets: { token: string }; }, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): SlackApiService => { const { token } = secrets; const { allowedChannels } = config || { allowedChannels: [] }; @@ -139,6 +141,7 @@ export const createExternalService = ( method: 'get', headers, url: `${SLACK_URL}conversations.info?channel=${channelId}`, + connectorUsageCollector, }); }; if (channelId.length === 0) { @@ -207,6 +210,7 @@ export const createExternalService = ( data: { channel: channelToUse, text }, headers, configurationUtilities, + connectorUsageCollector, }); return buildSlackExecutorSuccessResponse({ slackApiResponseData: result.data }); @@ -232,6 +236,7 @@ export const createExternalService = ( data: { channel: channelToUse, blocks: blockJson.blocks }, headers, configurationUtilities, + connectorUsageCollector, }); return buildSlackExecutorSuccessResponse({ slackApiResponseData: result.data }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts index d24febcccaad3..bbe53e86e068e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts @@ -76,7 +76,15 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: SwimlaneExecutorResultData | null = null; @@ -86,7 +94,8 @@ async function executor( secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts index 1aeee9c586fd5..5c04d60bed9c1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts @@ -14,6 +14,7 @@ import { request, createAxiosResponse } from '@kbn/actions-plugin/server/lib/axi import { createExternalService } from './service'; import { mappings } from './mocks'; import { ExternalService } from './types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -56,8 +57,13 @@ describe('Swimlane Service', () => { }; const url = config.apiUrl.slice(0, -1); + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { // The trailing slash at the end of the url is intended. @@ -66,7 +72,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); beforeEach(() => { @@ -87,7 +94,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -104,7 +112,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -122,7 +131,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -138,7 +148,8 @@ describe('Swimlane Service', () => { }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }).toThrow(); }); @@ -191,6 +202,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record`, method: 'post', configurationUtilities, + connectorUsageCollector, }); }); @@ -274,6 +286,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record/${incidentId}`, method: 'patch', configurationUtilities, + connectorUsageCollector, }); }); @@ -353,6 +366,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record/${incidentId}/${mappings.commentsConfig.id}/comment`, method: 'post', configurationUtilities, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts index 42c4b65408f21..4abe7f08de5c5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts @@ -14,6 +14,7 @@ import { throwIfResponseIsNotValid, } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { getBodyForEventAction } from './helpers'; import { CreateCommentParams, @@ -42,7 +43,8 @@ const createErrorMessage = (errorResponse: ResponseError | null | undefined): st export const createExternalService = ( { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { apiUrl: url, appId, mappings } = config as SwimlanePublicConfigurationType; const { apiToken } = secrets as SwimlaneSecretConfigurationType; @@ -92,6 +94,7 @@ export const createExternalService = ( logger, method: 'post', url: getPostRecordUrl(appId), + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -132,6 +135,7 @@ export const createExternalService = ( logger, method: 'patch', url: getPostRecordIdUrl(appId, params.incidentId), + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -181,6 +185,7 @@ export const createExternalService = ( logger, method: 'post', url: getPostCommentUrl(appId, incidentId, fieldId), + connectorUsageCollector, }); /** diff --git a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts index 0b144bceb05c7..6b1b0cf105d9d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts @@ -6,7 +6,7 @@ */ import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import axios from 'axios'; import { getConnectorType, TeamsConnectorType, ConnectorTypeId } from '.'; @@ -34,10 +34,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: TeamsConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -167,11 +172,42 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from teams action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": Object { "text": "this invocation should succeed", }, @@ -223,11 +259,42 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from teams action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": Object { "text": "this invocation should succeed", }, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts index 84aa7449725c8..9ab0fe4d428d7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts @@ -119,7 +119,8 @@ function validateConnectorTypeConfig( async function teamsExecutor( execOptions: TeamsConnectorTypeExecutorOptions ): Promise> { - const { actionId, secrets, params, configurationUtilities, logger } = execOptions; + const { actionId, secrets, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; const { webhookUrl } = secrets; const { message } = params; const data = { text: message }; @@ -134,6 +135,7 @@ async function teamsExecutor( logger, data, configurationUtilities, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts index 6218d48ae33fa..5972d5da570ef 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts @@ -18,17 +18,20 @@ import { PushToServiceIncidentSchema, } from '../../../common/thehive/schema'; import type { ExecutorSubActionCreateAlertParams, Incident } from '../../../common/thehive/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const mockTime = new Date('2024-04-03T09:10:30.000'); describe('TheHiveConnector', () => { + const logger = loggingSystemMock.createLogger(); + const connector = new TheHiveConnector( { configurationUtilities: actionsConfigMock.create(), connector: { id: '1', type: THEHIVE_CONNECTOR_ID }, config: { url: 'https://example.com', organisation: null }, secrets: { apiKey: 'test123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }, PushToServiceIncidentSchema @@ -36,6 +39,7 @@ describe('TheHiveConnector', () => { let mockRequest: jest.Mock; let mockError: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { jest.useFakeTimers(); @@ -51,6 +55,10 @@ describe('TheHiveConnector', () => { throw new Error('API Error'); }); jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('createIncident', () => { @@ -124,18 +132,21 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.createIncident(incident); + const response = await connector.createIncident(incident, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case', - method: 'post', - responseSchema: TheHiveIncidentResponseSchema, - data: incident, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case', + method: 'post', + responseSchema: TheHiveIncidentResponseSchema, + data: incident, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ id: '~172064', url: 'https://example.com/cases/~172064/details', @@ -148,7 +159,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.createIncident(incident)).rejects.toThrow('API Error'); + await expect(connector.createIncident(incident, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); @@ -173,18 +186,24 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.updateIncident({ incidentId: '~172064', incident }); + const response = await connector.updateIncident( + { incidentId: '~172064', incident }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064', - method: 'patch', - responseSchema: TheHiveUpdateIncidentResponseSchema, - data: incident, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064', + method: 'patch', + responseSchema: TheHiveUpdateIncidentResponseSchema, + data: incident, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ id: '~172064', url: 'https://example.com/cases/~172064/details', @@ -197,9 +216,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.updateIncident({ incidentId: '~172064', incident })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.updateIncident({ incidentId: '~172064', incident }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -224,21 +243,27 @@ describe('TheHiveConnector', () => { }); it('TheHive API call is successful with correct parameters', async () => { - await connector.addComment({ - incidentId: '~172064', - comment: 'test comment', - }); + await connector.addComment( + { + incidentId: '~172064', + comment: 'test comment', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064/comment', - method: 'post', - responseSchema: TheHiveAddCommentResponseSchema, - data: { message: 'test comment' }, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064/comment', + method: 'post', + responseSchema: TheHiveAddCommentResponseSchema, + data: { message: 'test comment' }, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { @@ -246,7 +271,10 @@ describe('TheHiveConnector', () => { connector.request = mockError; await expect( - connector.addComment({ incidentId: '~172064', comment: 'test comment' }) + connector.addComment( + { incidentId: '~172064', comment: 'test comment' }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); @@ -314,16 +342,19 @@ describe('TheHiveConnector', () => { }); it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.getIncident({ id: '~172064' }); + const response = await connector.getIncident({ id: '~172064' }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064', - responseSchema: TheHiveIncidentResponseSchema, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064', + responseSchema: TheHiveIncidentResponseSchema, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -331,7 +362,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.getIncident({ id: '~172064' })).rejects.toThrow('API Error'); + await expect( + connector.getIncident({ id: '~172064' }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -385,25 +418,30 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - await connector.createAlert(alert); + await connector.createAlert(alert, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/alert', - method: 'post', - responseSchema: TheHiveCreateAlertResponseSchema, - data: alert, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/alert', + method: 'post', + responseSchema: TheHiveCreateAlertResponseSchema, + data: alert, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.createAlert(alert)).rejects.toThrow('API Error'); + await expect(connector.createAlert(alert, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts index fe0caf8788f28..623a9b8ee73d7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts @@ -8,6 +8,7 @@ import { ServiceParams, CaseConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { Type } from '@kbn/config-schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SUB_ACTION } from '../../../common/thehive/constants'; import { TheHiveIncidentResponseSchema, @@ -68,14 +69,20 @@ export class TheHiveConnector extends CaseConnector< return `API Error: ${error.response?.data?.type} - ${error.response?.data?.message}`; } - public async createIncident(incident: Incident): Promise { - const res = await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/case`, - data: incident, - headers: this.getAuthHeaders(), - responseSchema: TheHiveIncidentResponseSchema, - }); + public async createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/case`, + data: incident, + headers: this.getAuthHeaders(), + responseSchema: TheHiveIncidentResponseSchema, + }, + connectorUsageCollector + ); return { id: res.data._id, @@ -85,30 +92,42 @@ export class TheHiveConnector extends CaseConnector< }; } - public async addComment({ incidentId, comment }: { incidentId: string; comment: string }) { - await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/case/${incidentId}/comment`, - data: { message: comment }, - headers: this.getAuthHeaders(), - responseSchema: TheHiveAddCommentResponseSchema, - }); + public async addComment( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { + await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/case/${incidentId}/comment`, + data: { message: comment }, + headers: this.getAuthHeaders(), + responseSchema: TheHiveAddCommentResponseSchema, + }, + connectorUsageCollector + ); } - public async updateIncident({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }): Promise { - await this.request({ - method: 'patch', - url: `${this.url}/api/${API_VERSION}/case/${incidentId}`, - data: incident, - headers: this.getAuthHeaders(), - responseSchema: TheHiveUpdateIncidentResponseSchema, - }); + public async updateIncident( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + await this.request( + { + method: 'patch', + url: `${this.url}/api/${API_VERSION}/case/${incidentId}`, + data: incident, + headers: this.getAuthHeaders(), + responseSchema: TheHiveUpdateIncidentResponseSchema, + }, + connectorUsageCollector + ); return { id: incidentId, @@ -118,23 +137,35 @@ export class TheHiveConnector extends CaseConnector< }; } - public async getIncident({ id }: { id: string }): Promise { - const res = await this.request({ - url: `${this.url}/api/${API_VERSION}/case/${id}`, - headers: this.getAuthHeaders(), - responseSchema: TheHiveIncidentResponseSchema, - }); + public async getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.request( + { + url: `${this.url}/api/${API_VERSION}/case/${id}`, + headers: this.getAuthHeaders(), + responseSchema: TheHiveIncidentResponseSchema, + }, + connectorUsageCollector + ); return res.data; } - public async createAlert(alert: ExecutorSubActionCreateAlertParams) { - await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/alert`, - data: alert, - headers: this.getAuthHeaders(), - responseSchema: TheHiveCreateAlertResponseSchema, - }); + public async createAlert( + alert: ExecutorSubActionCreateAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/alert`, + data: alert, + headers: this.getAuthHeaders(), + responseSchema: TheHiveCreateAlertResponseSchema, + }, + connectorUsageCollector + ); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts index b30a888f27998..6bbaad9b86a0c 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts @@ -12,6 +12,7 @@ import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { TinesConnector } from './tines'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { API_MAX_RESULTS, TINES_CONNECTOR_ID } from '../../../common/tines/constants'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); (axios as jest.Mocked).create.mockImplementation( @@ -78,6 +79,7 @@ const storiesGetRequestExpected = { 'Content-Type': 'application/json', }, params: { per_page: API_MAX_RESULTS }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }; const agentsGetRequestExpected = { @@ -91,20 +93,28 @@ const agentsGetRequestExpected = { 'Content-Type': 'application/json', }, params: { story_id: story.id, per_page: API_MAX_RESULTS }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }; +let connectorUsageCollector: ConnectorUsageCollector; + describe('TinesConnector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new TinesConnector({ configurationUtilities: actionsConfigMock.create(), config: { url }, connector: { id: '1', type: TINES_CONNECTOR_ID }, secrets: { email, token }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('getStories', () => { @@ -113,13 +123,13 @@ describe('TinesConnector', () => { }); it('should request Tines stories', async () => { - await connector.getStories(); + await connector.getStories(undefined, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith(storiesGetRequestExpected); }); it('should return the Tines stories reduced array', async () => { - const { stories } = await connector.getStories(); + const { stories } = await connector.getStories(undefined, connectorUsageCollector); expect(stories).toEqual([storyResult]); }); @@ -127,7 +137,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { stories: [story], meta: { pages: 1 } }, }); - const response = await connector.getStories(); + const response = await connector.getStories(undefined, connectorUsageCollector); expect(response.incompleteResponse).toEqual(false); }); @@ -135,7 +145,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { stories: [story], meta: { pages: 2 } }, }); - const response = await connector.getStories(); + const response = await connector.getStories(undefined, connectorUsageCollector); expect(response.incompleteResponse).toEqual(true); }); }); @@ -146,14 +156,17 @@ describe('TinesConnector', () => { }); it('should request Tines webhook actions', async () => { - await connector.getWebhooks({ storyId: story.id }); + await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith(agentsGetRequestExpected); }); it('should return the Tines webhooks reduced array', async () => { - const { webhooks } = await connector.getWebhooks({ storyId: story.id }); + const { webhooks } = await connector.getWebhooks( + { storyId: story.id }, + connectorUsageCollector + ); expect(webhooks).toEqual([webhookResult]); }); @@ -161,7 +174,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { agents: [webhookAgent], meta: { pages: 1 } }, }); - const response = await connector.getWebhooks({ storyId: story.id }); + const response = await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(response.incompleteResponse).toEqual(false); }); @@ -169,7 +182,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { agents: [webhookAgent], meta: { pages: 2 } }, }); - const response = await connector.getWebhooks({ storyId: story.id }); + const response = await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(response.incompleteResponse).toEqual(true); }); }); @@ -180,10 +193,13 @@ describe('TinesConnector', () => { }); it('should send data to Tines webhook using selected webhook parameter', async () => { - await connector.runWebhook({ - webhook: webhookResult, - body: '[]', - }); + await connector.runWebhook( + { + webhook: webhookResult, + body: '[]', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith({ @@ -194,14 +210,18 @@ describe('TinesConnector', () => { headers: { 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('should send data to Tines webhook using webhook url parameter', async () => { - await connector.runWebhook({ - webhookUrl, - body: '[]', - }); + await connector.runWebhook( + { + webhookUrl, + body: '[]', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith({ @@ -212,6 +232,7 @@ describe('TinesConnector', () => { headers: { 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts index cb46a9abea3cc..ed98ec382af86 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts @@ -6,6 +6,7 @@ */ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { @@ -108,12 +109,16 @@ export class TinesConnector extends SubActionConnector( req: SubActionRequestParams, - reducer: (response: R) => T + reducer: (response: R) => T, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request({ - ...req, - params: { ...req.params, per_page: API_MAX_RESULTS }, - }); + const response = await this.request( + { + ...req, + params: { ...req.params, per_page: API_MAX_RESULTS }, + }, + connectorUsageCollector + ); return { ...reducer(response.data), incompleteResponse: response.data.meta.pages > 1, @@ -130,20 +135,25 @@ export class TinesConnector extends SubActionConnector { + public async getStories( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { return this.tinesApiRequest( { url: this.urls.stories, headers: this.getAuthHeaders(), responseSchema: TinesStoriesApiResponseSchema, }, - storiesReducer + storiesReducer, + connectorUsageCollector ); } - public async getWebhooks({ - storyId, - }: TinesWebhooksActionParams): Promise { + public async getWebhooks( + { storyId }: TinesWebhooksActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { return this.tinesApiRequest( { url: this.urls.agents, @@ -151,24 +161,27 @@ export class TinesConnector extends SubActionConnector { + public async runWebhook( + { webhook, webhookUrl, body }: TinesRunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { if (!webhook && !webhookUrl) { throw Error('Invalid subActionsParams: [webhook] or [webhookUrl] expected but got none'); } - const response = await this.request({ - url: webhookUrl ? webhookUrl : this.urls.getRunWebhookURL(webhook!), - method: 'post', - responseSchema: TinesRunApiResponseSchema, - data: body, - }); + const response = await this.request( + { + url: webhookUrl ? webhookUrl : this.urls.getRunWebhookURL(webhook!), + method: 'post', + responseSchema: TinesRunApiResponseSchema, + data: body, + }, + connectorUsageCollector + ); return response.data; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap b/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000000..e8260c86f3e00 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`execute Torq action execute with token happy flow 1`] = ` +Object { + "axios": Any, + "connectorUsageCollector": Object { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from Torq action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, + "data": Object { + "msg": "some data", + }, + "headers": Object { + "Content-Type": "application/json", + "X-Torq-Token": "1234", + }, + "logger": Any, + "method": "post", + "url": "https://hooks.torq.io/v1/test", + "validateStatus": Any, +} +`; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts index 4bf60d10eb789..39bbdd44a918d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts @@ -12,6 +12,7 @@ import { ActionTypeConfigType, getActionType, TorqActionType } from '.'; import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { Services } from '@kbn/actions-plugin/server/types'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; @@ -37,10 +38,15 @@ const services: Services = actionsMock.createServices(); let actionType: TorqActionType; const mockedLogger: jest.Mocked = loggerMock.create(); let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { actionType = getActionType(); configurationUtilities = actionsConfigMock.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('actionType', () => { @@ -171,48 +177,29 @@ describe('execute Torq action', () => { params: { body: '{"msg": "some data"}' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; - expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` - Object { - "axios": [MockFunction], - "data": Object { - "msg": "some data", - }, - "headers": Object { - "Content-Type": "application/json", - "X-Torq-Token": "1234", + expect(requestMock.mock.calls[0][0]).toMatchSnapshot({ + axios: expect.any(Function), + connectorUsageCollector: { + usage: { + requestBodyBytes: 0, }, - "logger": Object { - "context": Array [], - "debug": [MockFunction] { - "calls": Array [ - Array [ - "response from Torq action \\"some-id\\": [HTTP 200] ", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - }, - "error": [MockFunction], - "fatal": [MockFunction], - "get": [MockFunction], - "info": [MockFunction], - "isLevelEnabled": [MockFunction], - "log": [MockFunction], - "trace": [MockFunction], - "warn": [MockFunction], - }, - "method": "post", - "url": "https://hooks.torq.io/v1/test", - "validateStatus": [Function], - } - `); + }, + data: { + msg: 'some data', + }, + headers: { + 'Content-Type': 'application/json', + 'X-Torq-Token': '1234', + }, + logger: expect.any(Object), + method: 'post', + url: 'https://hooks.torq.io/v1/test', + validateStatus: expect.any(Function), + }); }); test('renders parameter templates as expected', async () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts index c3e7dc4f1533c..b60237dd7991e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts @@ -146,6 +146,7 @@ export async function executor( const { webhookIntegrationUrl } = execOptions.config; const { body: data } = execOptions.params; const configurationUtilities = execOptions.configurationUtilities; + const connectorUsageCollector = execOptions.connectorUsageCollector; const secrets: ActionTypeSecretsType = execOptions.secrets; const token = secrets.token; @@ -171,6 +172,7 @@ export async function executor( configurationUtilities, logger: execOptions.logger, validateStatus: (status: number) => status >= 200 && status < 300, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap b/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000000..f52e34d90dbf0 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`execute() execute with username/password sends request with basic auth 1`] = ` +Object { + "axios": undefined, + "connectorUsageCollector": Object { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, + "data": "some data", + "headers": Object { + "Authorization": "Basic YWJjOjEyMw==", + "aheader": "a value", + }, + "logger": Any, + "method": "post", + "sslOverrides": Object {}, + "url": "https://abc.def/my-webhook", +} +`; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts index 6c51fe11e97de..724daa852019f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; @@ -41,10 +41,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: WebhookConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connectorType', () => { @@ -339,46 +344,27 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; - expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` - Object { - "axios": undefined, - "data": "some data", - "headers": Object { - "Authorization": "Basic YWJjOjEyMw==", - "aheader": "a value", - }, - "logger": Object { - "context": Array [], - "debug": [MockFunction] { - "calls": Array [ - Array [ - "response from webhook action \\"some-id\\": [HTTP 200] ", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - }, - "error": [MockFunction], - "fatal": [MockFunction], - "get": [MockFunction], - "info": [MockFunction], - "isLevelEnabled": [MockFunction], - "log": [MockFunction], - "trace": [MockFunction], - "warn": [MockFunction], + expect(requestMock.mock.calls[0][0]).toMatchSnapshot({ + axios: undefined, + connectorUsageCollector: { + usage: { + requestBodyBytes: 0, }, - "method": "post", - "sslOverrides": Object {}, - "url": "https://abc.def/my-webhook", - } - `); + }, + data: 'some data', + headers: { + Authorization: 'Basic YWJjOjEyMw==', + aheader: 'a value', + }, + logger: expect.any(Object), + method: 'post', + sslOverrides: {}, + url: 'https://abc.def/my-webhook', + }); }); test('execute with ssl adds ssl settings to sslOverrides', async () => { @@ -400,6 +386,7 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; @@ -407,6 +394,36 @@ describe('execute()', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "some data", "headers": Object { "aheader": "a value", @@ -588,6 +605,7 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.error).toBeCalledWith( 'error on some-id webhook event: maxContentLength size of 1000000 exceeded' @@ -618,12 +636,43 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "some data", "headers": Object { "aheader": "a value", diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts index 78f02d24b9b87..f7c7fd4f6d61e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts @@ -128,7 +128,8 @@ function validateConnectorTypeConfig( export async function executor( execOptions: WebhookConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, params, configurationUtilities, logger } = execOptions; + const { actionId, config, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; const { method, url, headers = {}, hasAuth, authType, ca, verificationMode } = config; const { body: data } = params; @@ -159,6 +160,7 @@ export async function executor( data, configurationUtilities, sslOverrides, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts index 9205c3fef91c9..b357faffc8a0b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts @@ -14,7 +14,7 @@ import { XmattersConnectorType, } from '.'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateConnector, @@ -45,10 +45,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: XmattersConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connectorType', () => { @@ -423,6 +428,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); const { method, url, headers, data } = requestMock.mock.calls[0][0]; @@ -472,6 +478,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.warn).toBeCalledWith( 'Error thrown triggering xMatters workflow: maxContentLength size of 1000000 exceeded' @@ -504,6 +511,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); const { method, url, headers, data } = requestMock.mock.calls[0][0]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts index 880c2278ca923..ad189bda9defb 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts @@ -8,7 +8,7 @@ import { isString } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; -import type { +import { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, ActionTypeExecutorResult as ConnectorTypeExecutorResult, @@ -247,7 +247,8 @@ function validateConnectorTypeSecrets( export async function executor( execOptions: XmattersConnectorTypeExecutorOptions ): Promise> { - const { actionId, configurationUtilities, config, params, logger } = execOptions; + const { actionId, configurationUtilities, config, params, logger, connectorUsageCollector } = + execOptions; const { configUrl, usesBasic } = config; const data = getPayloadForRequest(params); @@ -263,7 +264,12 @@ export async function executor( if (!url) { throw new Error('Error: no url provided'); } - result = await postXmatters({ url, data, basicAuth }, logger, configurationUtilities); + result = await postXmatters( + { url, data, basicAuth }, + logger, + configurationUtilities, + connectorUsageCollector + ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.xmatters.postingErrorMessage', { defaultMessage: 'Error triggering xMatters workflow', diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts index 2c2a08901cec3..215d1942c6e8a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts @@ -10,6 +10,7 @@ import { Logger } from '@kbn/core/server'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; interface PostXmattersOptions { url: string; @@ -34,7 +35,8 @@ interface PostXmattersOptions { export async function postXmatters( options: PostXmattersOptions, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { url, data, basicAuth } = options; const axiosInstance = axios.create(); @@ -50,5 +52,6 @@ export async function postXmatters( data, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); } diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts index 7bd9db83dcc00..302bbf2b06668 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts @@ -11,6 +11,7 @@ import type { ServiceParams } from '@kbn/actions-plugin/server'; import { PluginSetupContract as ActionsPluginSetup } from '@kbn/actions-plugin/server/plugin'; import { schema, TypeOf } from '@kbn/config-schema'; import { SubActionConnectorType } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const TestConfigSchema = schema.object({ url: schema.string() }); const TestSecretsSchema = schema.object({ @@ -69,7 +70,11 @@ export const getTestSubActionConnector = ( return `Message: ${error.response?.data.errorMessage}. Code: ${error.response?.data.errorCode}`; } - public async subActionWithParams({ id }: { id: string }) { + public async subActionWithParams( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { + connectorUsageCollector.addRequestBodyBytes(undefined, { id }); return { id }; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts index 1b39410a7bf93..3bc7b665e2c2e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts @@ -13,8 +13,9 @@ import { } from '@kbn/actions-simulators-plugin/server/bedrock_simulation'; import { DEFAULT_TOKEN_LIMIT } from '@kbn/stack-connectors-plugin/common/bedrock/constants'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; const connectorTypeId = '.bedrock'; const name = 'A bedrock action'; @@ -344,6 +345,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(145); }); it('should overwrite the model when a model argument is provided', async () => { @@ -374,6 +392,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(145); }); it('should invoke AI with assistant AI body argument formatted to bedrock expectations', async () => { @@ -423,6 +458,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { connector_id: bedrockActionId, data: { message: bedrockClaude2SuccessResponse.completion }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(256); }); describe('Token tracking dashboard', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts index f26ba86f6fa3a..1ef7b170a4f0d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts @@ -14,13 +14,16 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function casesWebhookTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); const config = { createCommentJson: '{"body":{{{case.comment}}}}', createCommentMethod: 'post', @@ -398,6 +401,23 @@ export default function casesWebhookTest({ getService }: FtrProviderContext) { const { pushedDate, ...dataWithoutTime } = body.data; body.data = dataWithoutTime; + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(125); + expect(body).to.eql({ status: 'ok', connector_id: simulatedActionId, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts index 7e1f0636b3a96..72cea764d0165 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts @@ -12,7 +12,9 @@ import { d3SecuritySuccessResponse, } from '@kbn/actions-simulators-plugin/server/d3security_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.d3security'; const name = 'A D3 Security action'; @@ -24,6 +26,7 @@ const secrets = { export default function d3SecurityTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const createConnector = async (url: string) => { const { body } = await supertest @@ -248,6 +251,24 @@ export default function d3SecurityTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: d3SecurityActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(99); + expect(body).to.eql({ status: 'ok', connector_id: d3SecurityActionId, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts index cfffe90126fac..6ed2c89e094f9 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts @@ -11,12 +11,15 @@ import { ExternalServiceSimulator, getExternalServiceSimulatorPath, } from '@kbn/actions-simulators-plugin/server/plugin'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function emailTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); + const retry = getService('retry'); describe('create email action', () => { let createdActionId = ''; @@ -103,7 +106,7 @@ export default function emailTest({ getService }: FtrProviderContext) { }, }) .expect(200) - .then((resp: any) => { + .then(async (resp: any) => { expect(resp.body.data.message.messageId).to.be.a('string'); expect(resp.body.data.messageId).to.be.a('string'); @@ -131,6 +134,23 @@ export default function emailTest({ getService }: FtrProviderContext) { headers: {}, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: createdActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(350); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts index 46287db208b87..8d867aea49685 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts @@ -7,7 +7,9 @@ import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; @@ -16,6 +18,7 @@ export default function indexTest({ getService }: FtrProviderContext) { const es: Client = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); + const retry = getService('retry'); describe('index action', () => { beforeEach(() => esDeleteAllIndices(ES_TEST_INDEX_NAME)); @@ -214,6 +217,23 @@ export default function indexTest({ getService }: FtrProviderContext) { } expect(passed1).to.be(true); expect(passed2).to.be(true); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: createdAction.id, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); it('should execute successly with refresh false', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts index 054678996888f..2268e379f441a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -16,12 +17,14 @@ import { import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_OTHER_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/jira/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function jiraTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); const mockJira = { config: { @@ -517,6 +520,23 @@ export default function jiraTest({ getService }: FtrProviderContext) { url: `${jiraSimulatorURL}/browse/CK-1`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(124); }); it('should handle creating an incident with other fields', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts index 716041e939e8a..05dfc61dd59e3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { OpenAISimulator, @@ -14,6 +15,7 @@ import { import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.gen-ai'; const name = 'A genAi action'; @@ -315,6 +317,23 @@ export default function genAiTest({ getService }: FtrProviderContext) { connector_id: genAiActionId, data: genAiSuccessResponse, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: genAiActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(78); }); describe('Token tracking dashboard', () => { const dashboardId = 'specific-dashboard-id-default'; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts index 48386480b00da..75913a4182bbd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { OpsgenieSimulator, @@ -13,11 +14,13 @@ import { } from '@kbn/actions-simulators-plugin/server/opsgenie_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function opsgenieTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); describe('Opsgenie', () => { describe('action creation', () => { @@ -535,6 +538,23 @@ export default function opsgenieTest({ getService }: FtrProviderContext) { connector_id: opsgenieActionId, data: opsgenieSuccessResponse, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: opsgenieActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(21); }); it('should preserve the alias when it is 512 characters when creating an alert', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts index 7148ac962c728..2871066b6456a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function pagerdutyTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('pagerduty action', () => { let simulatedActionId = ''; @@ -173,6 +176,23 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) { status: 'success', }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(142); }); it('should execute successfully with links and customDetails', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts index c9b4e7ecafa3f..6dfb420463e9f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts @@ -6,15 +6,18 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { ResilientSimulator } from '@kbn/actions-simulators-plugin/server/resilient_simulation'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function resilientTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockResilient = { config: { @@ -409,6 +412,23 @@ export default function resilientTest({ getService }: FtrProviderContext) { url: `${simulatorUrl}/#incidents/123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: resilientActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(167); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts index a5f14e512ddb1..a3fedba5d1f69 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts @@ -6,12 +6,15 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serverLogTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const retry = getService('retry'); describe('server-log action', () => { let serverLogActionId: string; @@ -69,6 +72,23 @@ export default function serverLogTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: serverLogActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts index 4702d3bbe6df7..0f1748db4f5ef 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts @@ -10,16 +10,19 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowITOMTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { params: { @@ -500,6 +503,23 @@ export default function serviceNowITOMTest({ getService }: FtrProviderContext) { }) .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(317); }); }); @@ -548,6 +568,23 @@ export default function serviceNowITOMTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 2 }], + ['execute', { equal: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts index ec62e6d30f6ff..bc0f48f15caf5 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts @@ -10,17 +10,20 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_ADDITIONAL_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/servicenow/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowITSMTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { params: { @@ -708,6 +711,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(261); }); }); @@ -755,6 +775,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(239); }); }); @@ -803,6 +840,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); @@ -829,6 +883,22 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { connector_id: simulatedActionId, data: {}, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts index fd4781f6d9e62..717a44a406712 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts @@ -10,17 +10,20 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_ADDITIONAL_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/servicenow/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowSIRTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { config: { @@ -721,6 +724,23 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=sn_si_incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(645); }); }); @@ -768,6 +788,22 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=sn_si_incident.do?sys_id=123`, }, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(429); }); }); @@ -816,6 +852,23 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts index 4941bec1844ca..457f9edbed2fc 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts @@ -9,14 +9,18 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; import http from 'http'; import getPort from 'get-port'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; + import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getSlackServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function slackTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); describe('Slack webhook action', () => { let simulatedActionId = ''; @@ -175,6 +179,23 @@ export default function slackTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); expect(proxyHaveBeenCalled).to.equal(true); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(18); }); it('should handle an empty message error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts index 859f4f952fe58..4d91fdddf80dd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts @@ -9,16 +9,19 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getSwimlaneServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function swimlaneTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockSwimlane = { name: 'A swimlane action', @@ -459,6 +462,23 @@ export default function swimlaneTest({ getService }: FtrProviderContext) { url: `${swimlaneSimulatorURL}/record/123456asdf/wowzeronza`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(175); }); it('should handle updating an incident', async () => { @@ -490,6 +510,23 @@ export default function swimlaneTest({ getService }: FtrProviderContext) { url: `${swimlaneSimulatorURL}/record/123456asdf/wowzeronza`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(193); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts index 53dd3aaaf026a..04971990f879e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { TinesSimulator, @@ -16,6 +17,7 @@ import { } from '@kbn/actions-simulators-plugin/server/tines_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.tines'; const name = 'A tines action'; @@ -35,6 +37,7 @@ const webhook = { export default function tinesTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const createConnector = async (url: string) => { const { body } = await supertest @@ -392,6 +395,23 @@ export default function tinesTest({ getService }: FtrProviderContext) { incompleteResponse: false, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should get webhooks', async () => { @@ -422,6 +442,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { incompleteResponse: false, }, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should run the webhook', async () => { @@ -440,6 +476,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { connector_id: tinesActionId, data: tinesWebhookSuccessResponse, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(8); }); it('should run the webhook url', async () => { @@ -464,6 +516,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { connector_id: tinesActionId, data: tinesWebhookSuccessResponse, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(8); }); }); @@ -506,6 +574,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { errorSource: TaskErrorSource.FRAMEWORK, service_message: 'Status code: 422. Message: API Error: Unprocessable Entity', }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should return a failure when attempting to get webhooks', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts index 257378b406da5..b709ef837ad03 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers/get_proxy_server'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function torqTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('Torq action', () => { let simulatedActionId = ''; @@ -159,6 +162,22 @@ export default function torqTest({ getService }: FtrProviderContext) { connector_id: simulatedActionId, data: `{"msg": "test"}`, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(14); }); it('should handle a 400 Torq error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts index c7a8f1c1b2524..f05db95254c1c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts @@ -8,6 +8,8 @@ import httpProxy from 'http-proxy'; import http from 'http'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; + import { URL, format as formatUrl } from 'url'; import getPort from 'get-port'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; @@ -17,6 +19,7 @@ import { getWebhookServer, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const defaultValues: Record = { headers: null, @@ -36,6 +39,7 @@ export default function webhookTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); async function createWebhookAction( webhookSimulatorURL: string, @@ -258,6 +262,23 @@ export default function webhookTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: webhookActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(19); }); it('should support the PUT method against webhook target', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts index 4efacbf78f951..7cf2320c97933 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function xmattersTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('xmatters action', () => { let simulatedActionId = ''; @@ -180,6 +183,23 @@ export default function xmattersTest({ getService }: FtrProviderContext) { spaceId: '', }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(130); }); it('should handle a 40x xmatters error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts index acfb06e64cff6..f7b62d51d635f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts @@ -652,6 +652,8 @@ export default function ({ getService }: FtrProviderContext) { expect(executeEvent?.message).to.eql(message); expect(startExecuteEvent?.message).to.eql(message.replace('executed', 'started')); + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.eql(0); + if (source) { expect(executeEvent?.kibana?.action?.execution?.source).to.eql(source.toLowerCase()); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts index c8fb3e4b6ce2d..b504f8204c4aa 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts @@ -8,8 +8,9 @@ import type SuperTest from 'supertest'; import expect from '@kbn/expect'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; /** * The sub action connector is defined here @@ -79,6 +80,7 @@ const executeSubAction = async ({ // eslint-disable-next-line import/no-default-export export default function createActionTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const retry = getService('retry'); describe('Sub action framework', () => { const objectRemover = new ObjectRemover(supertest); @@ -140,13 +142,35 @@ export default function createActionTests({ getService }: FtrProviderContext) { const res = await createSubActionConnector({ supertest }); objectRemover.add('default', res.body.id, 'action', 'actions'); + const connectorId = res.body.id as string; + const subActionParams = { id: 'test-id' }; + const execRes = await executeSubAction({ supertest, - connectorId: res.body.id as string, + connectorId, subAction: 'subActionWithParams', - subActionParams: { id: 'test-id' }, + subActionParams, + }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: connectorId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); }); + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.eql( + Buffer.byteLength(JSON.stringify(subActionParams)) + ); + expect(execRes.body).to.eql({ status: 'ok', data: { id: 'test-id' }, From b386e1ccfe818231a364695a9a97d7ef76da6c6a Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 27 Aug 2024 11:58:08 +0200 Subject: [PATCH 26/38] [EDR Workflows][Osquery] Prevent pack creation on shards field error (#191186) It was observed that even though we display an error on Shard policy field if the field is left empty we still proceed with displaying confirmation modal which does nothing on selecting "Save and deploy changes". https://github.com/user-attachments/assets/0506894d-9e93-4233-8ac3-442968b6f848 With this change form behaves as expected, with a field error it won't proceed with form submission. https://github.com/user-attachments/assets/0168ccf7-4137-43d4-8005-589be3ae0e35 --- .../packs/form/shards/shards_policy_field.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx b/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx index bf4bdf0540bdc..bf14459f8edb0 100644 --- a/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx @@ -28,15 +28,17 @@ const ShardsPolicyFieldComponent = ({ }: ShardsPolicyFieldComponent) => { const { data: { agentPoliciesById } = {} } = useAgentPolicies(); + const missingValueError = i18n.translate( + 'xpack.osquery.pack.form.shardsPolicyFieldMissingErrorMessage', + { + defaultMessage: 'Policy is a required field', + } + ); + const policyFieldValidator = useCallback( - (policy: { key: string; label: string }) => - !policy - ? i18n.translate('xpack.osquery.pack.form.shardsPolicyFieldMissingErrorMessage', { - defaultMessage: 'Policy is a required field', - }) - : undefined, + (policy: { key: string; label: string }) => (!policy ? missingValueError : undefined), - [] + [missingValueError] ); const { @@ -47,6 +49,7 @@ const ShardsPolicyFieldComponent = ({ name: `shardsArray.${index}.policy`, rules: { validate: policyFieldValidator, + required: missingValueError, }, }); From b5570ecdc420cd4649ec63fe2a95f841481b487e Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:31:32 +0200 Subject: [PATCH 27/38] [Lens] fix flaky test with deleting filters (#191316) ## Summary Fixes https://github.com/elastic/kibana/issues/191009 (also fixes https://github.com/elastic/kibana/issues/189569 https://github.com/elastic/kibana/issues/178270 https://github.com/elastic/kibana/issues/139040 which are already closed as one time occurances but could happen again) https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6809 --- test/functional/services/filter_bar.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts index be4abf4e0daf2..c508410739db0 100644 --- a/test/functional/services/filter_bar.ts +++ b/test/functional/services/filter_bar.ts @@ -133,10 +133,11 @@ export class FilterBarService extends FtrService { * @param key field name */ public async removeFilter(key: string): Promise { - await this.retry.try(async () => { + await this.retry.waitFor('filter pill context menu is open', async () => { await this.testSubjects.click(`~filter & ~filter-key-${key}`); - await this.testSubjects.click(`deleteFilter`); + return await this.testSubjects.exists('deleteFilter'); }); + await this.testSubjects.click(`deleteFilter`); await this.header.awaitGlobalLoadingIndicatorHidden(); } From 1e428adc21c50fcb78a754d91eaee7ef5c1320ec Mon Sep 17 00:00:00 2001 From: Irene Blanco Date: Tue, 27 Aug 2024 13:44:54 +0200 Subject: [PATCH 28/38] [Infra][Hosts] Display N/A badge for APM hosts without system metrics (#191181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Closes https://github.com/elastic/kibana/issues/190516 This PR introduces an "N/A" badge for hosts that are returned by the `metrics/infra/host` API with `hasSystemMetrics` set to `false`. This enhancement will help users quickly identify and address issues with APM hosts that are not monitored by the system integration. The badge will provide an explanation of the problem and suggest troubleshooting steps. ![Screen Recording 2024-08-23 at 11 58 29](https://github.com/user-attachments/assets/e4e72ac5-5244-4863-915d-51b14ebf078a) **Automated tests** Upon reviewing the code, I noticed that this screen is covered by functional tests. My initial idea was to add some functional tests to verify the badge display as well as the button and link redirections. However, I found that this is quite complex, as it involves modifying the data used in the tests, and I’m still not very familiar with that process. Given the deadline for this epic, I’ve decided not to include tests in this issue. If we believe they are really necessary, I would need to spend some time understanding how data is managed in our functional testing layer. Any feedback on this would be greatly appreciated. --- .../add_data_troubleshooting_popover.tsx | 111 ++++++++++++++++++ .../hosts/hooks/use_hosts_table.test.ts | 4 +- .../metrics/hosts/hooks/use_hosts_table.tsx | 58 +++++++-- 3 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx new file mode 100644 index 0000000000000..419f78a892352 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx @@ -0,0 +1,111 @@ +/* + * 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 { + EuiBadge, + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiPopover, + EuiPopoverFooter, + EuiPopoverTitle, + EuiText, +} from '@elastic/eui'; + +import { + ObservabilityOnboardingLocatorParams, + OBSERVABILITY_ONBOARDING_LOCATOR, +} from '@kbn/deeplinks-observability'; +import { i18n } from '@kbn/i18n'; +import { useBoolean } from '@kbn/react-hooks'; + +import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana'; +import { APM_HOST_TROUBLESHOOTING_LINK } from '../../../../../components/asset_details/constants'; + +const popoverContent = { + title: i18n.translate('xpack.infra.addDataPopover.wantToSeeMorePopoverTitleLabel', { + defaultMessage: 'Want to see more?', + }), + content: i18n.translate('xpack.infra.addDataPopover.understandHostPerformanceByTextLabel', { + defaultMessage: 'Understand host performance by collecting more metrics.', + }), + button: i18n.translate('xpack.infra.addDataPopover.understandHostPerformanceByTextLabel', { + defaultMessage: 'Add data', + }), + link: i18n.translate('xpack.infra.addDataPopover.troubleshootingLinkLabel', { + defaultMessage: 'Troubleshooting', + }), +}; + +const badgeContent = i18n.translate('xpack.infra.addDataPopover.naBadgeLabel', { + defaultMessage: 'N/A', +}); + +export const AddDataTroubleshootingPopover = () => { + const [isPopoverOpen, { off: closePopover, toggle: togglePopover }] = useBoolean(false); + + const { + services: { share }, + } = useKibanaContextForPlugin(); + const addDataLinkHref = share.url.locators + .get(OBSERVABILITY_ONBOARDING_LOCATOR) + ?.getRedirectUrl({ category: 'logs' }); + + const onButtonClick = () => togglePopover(); + + return ( + + {badgeContent} + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + > + {popoverContent.title} + + {popoverContent.content} + + + + + + {popoverContent.button} + + + + + + {popoverContent.link} + + + + + + + ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts index 965f6acd24c93..a0ebb20184912 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useHostsTable } from './use_hosts_table'; +import { type HostNodeRow, useHostsTable } from './use_hosts_table'; import { renderHook } from '@testing-library/react-hooks'; import { InfraAssetMetricsItem } from '../../../../../common/http_api'; import * as useUnifiedSearchHooks from './use_unified_search'; @@ -158,7 +158,7 @@ describe('useHostTable hook', () => { } as unknown as ReturnType); }); it('it should map the nodes returned from the snapshot api to a format matching eui table items', () => { - const expected = [ + const expected: Array> = [ { name: 'host-0', os: '-', diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx index 4bdb72e625a89..e881950df570c 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx @@ -40,6 +40,7 @@ import { ColumnHeader } from '../components/table/column_header'; import { TABLE_COLUMN_LABEL, TABLE_CONTENT_LABEL } from '../translations'; import { METRICS_TOOLTIP } from '../../../../common/visualizations'; import { buildCombinedAssetFilter } from '../../../../utils/filters/build'; +import { AddDataTroubleshootingPopover } from '../components/table/add_data_troubleshooting_popover'; /** * Columns and items types @@ -64,10 +65,31 @@ export type HostNodeRow = HostMetadata & * Helper functions */ const formatMetric = (type: InfraAssetMetricType, value: number | undefined | null) => { - return value || value === 0 ? createInventoryMetricFormatter({ type })(value) : 'N/A'; + const defaultValue = value ?? 0; + return createInventoryMetricFormatter({ type })(defaultValue); +}; + +const buildMetricCell = ( + value: number | null, + formatType: InfraAssetMetricType, + hasSystemMetrics?: boolean +) => { + if (!hasSystemMetrics && value === null) { + return ; + } + + return formatMetric(formatType, value); }; const buildItemsList = (nodes: InfraAssetMetricsItem[]): HostNodeRow[] => { + nodes.map((node) => { + if (node.name === 'instance') { + node.metrics[0].value = 0; + node.hasSystemMetrics = true; + } + return node; + }); + return nodes.map(({ metrics, metadata, name, alertsCount, hasSystemMetrics }) => { const metadataKeyValue = metadata.reduce( (acc, curr) => ({ @@ -89,7 +111,7 @@ const buildItemsList = (nodes: InfraAssetMetricsItem[]): HostNodeRow[] => { ...metrics.reduce( (acc, curr) => ({ ...acc, - [curr.name]: curr.value ?? 0, + [curr.name]: curr.value, }), {} as HostMetrics ), @@ -104,12 +126,15 @@ const isTitleColumn = (cell: HostNodeRow[keyof HostNodeRow]): cell is HostNodeRo }; const sortValues = (aValue: any, bValue: any, { direction }: Sorting) => { - if (typeof aValue === 'string' && typeof bValue === 'string') { - return direction === 'desc' ? bValue.localeCompare(aValue) : aValue.localeCompare(bValue); + const a = aValue ?? -1; + const b = bValue ?? -1; + + if (typeof a === 'string' && typeof b === 'string') { + return direction === 'desc' ? b.localeCompare(a) : a.localeCompare(b); } - if (isNumber(aValue) && isNumber(bValue)) { - return direction === 'desc' ? bValue - aValue : aValue - bValue; + if (isNumber(a) && isNumber(b)) { + return direction === 'desc' ? b - a : a - b; } return 1; @@ -358,7 +383,8 @@ export const useHostsTable = () => { field: 'cpuV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-cpuUsage', - render: (avg: number) => formatMetric('cpuV2', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'cpuV2', hasSystemMetrics), align: 'right', }, { @@ -373,7 +399,8 @@ export const useHostsTable = () => { field: 'normalizedLoad1m', sortable: true, 'data-test-subj': 'hostsView-tableRow-normalizedLoad1m', - render: (avg: number) => formatMetric('normalizedLoad1m', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'normalizedLoad1m', hasSystemMetrics), align: 'right', }, { @@ -388,7 +415,8 @@ export const useHostsTable = () => { field: 'memory', sortable: true, 'data-test-subj': 'hostsView-tableRow-memoryUsage', - render: (avg: number) => formatMetric('memory', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'memory', hasSystemMetrics), align: 'right', }, { @@ -403,7 +431,8 @@ export const useHostsTable = () => { field: 'memoryFree', sortable: true, 'data-test-subj': 'hostsView-tableRow-memoryFree', - render: (avg: number) => formatMetric('memoryFree', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'memoryFree', hasSystemMetrics), align: 'right', }, { @@ -418,7 +447,8 @@ export const useHostsTable = () => { field: 'diskSpaceUsage', sortable: true, 'data-test-subj': 'hostsView-tableRow-diskSpaceUsage', - render: (max: number) => formatMetric('diskSpaceUsage', max), + render: (max: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(max, 'diskSpaceUsage', hasSystemMetrics), align: 'right', }, { @@ -433,7 +463,8 @@ export const useHostsTable = () => { field: 'rxV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-rx', - render: (avg: number) => formatMetric('rx', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'rx', hasSystemMetrics), align: 'right', }, { @@ -448,7 +479,8 @@ export const useHostsTable = () => { field: 'txV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-tx', - render: (avg: number) => formatMetric('tx', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'tx', hasSystemMetrics), align: 'right', }, ], From ffd4076538cdd41c41651a09e11fb3eef8144b85 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Tue, 27 Aug 2024 14:10:48 +0200 Subject: [PATCH 29/38] [Tines connector] Improve error handling and fallback (#191263) ## Summary From: https://github.com/elastic/kibana/issues/188115 Improvements of the Tines connector: - Original Axios error passed back from `getResponseErrorMessage` to the sub-actions framework, instead of returning `Unknown API error` string. The error appears in the error toast so the user has more information about the problem: Before: before After: after - Fallback input (direct webhook URL) now appears when there's some error. Before this change, the fallback input only appeared when the Tines API response was incomplete. Proper callout message added: Error fallback Co-authored-by: Elastic Machine --- .../tines/tines_params.test.tsx | 44 +++++++++++++++++++ .../connector_types/tines/tines_params.tsx | 21 ++++++++- .../connector_types/tines/translations.ts | 14 ++++++ .../connector_types/tines/tines.test.ts | 24 +++++++++- .../server/connector_types/tines/tines.ts | 9 ++-- 5 files changed, 103 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx index 495a15c6a569c..72bc2e3ae891f 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx @@ -467,6 +467,50 @@ describe('TinesParamsFields renders', () => { webhookUrl ); }); + + it('should render webhook url fallback when stories request has error', () => { + const errorMessage = 'something broke'; + mockUseSubActionStories.mockReturnValueOnce({ + isLoading: false, + response: { stories: [story] }, + error: new Error(errorMessage), + }); + + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true); + }); + + it('should render webhook url fallback when webhooks request has error', () => { + const errorMessage = 'something broke'; + mockUseSubActionWebhooks.mockReturnValueOnce({ + isLoading: false, + response: { webhooks: [webhook] }, + error: new Error(errorMessage), + }); + + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true); + }); }); describe('subActions error', () => { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx index 11249f9c8db3c..2726e0e3ec8a5 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx @@ -137,7 +137,10 @@ const TinesParamsFields: React.FunctionComponent(() => { + const showFallbackFrom = useMemo<'Story' | 'Webhook' | 'any' | 'error' | null>(() => { + if (storiesError || webhooksError) { + return 'error'; + } if (incompleteStories && !selectedStoryOption) { return 'Story'; } @@ -150,7 +153,9 @@ const TinesParamsFields: React.FunctionComponent - {showFallbackFrom !== 'any' && ( + {showFallbackFrom === 'error' && ( + <> + + {i18n.WEBHOOK_URL_ERROR_FALLBACK} + + + + )} + {(showFallbackFrom === 'Story' || showFallbackFrom === 'Webhook') && ( <> values: { entity, limit: API_MAX_RESULTS }, defaultMessage: `Not possible to retrieve more than {limit} results from the Tines {entity} API. If your {entity} does not appear in the list, please fill the Webhook URL below`, }); + +export const WEBHOOK_URL_ERROR_FALLBACK_TITLE = i18n.translate( + 'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallbackTitle', + { + defaultMessage: 'Error using Tines API', + } +); +export const WEBHOOK_URL_ERROR_FALLBACK = i18n.translate( + 'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallback', + { + defaultMessage: + 'There seems to be an issue retrieving Stories or Webhooks using the Tines API. Alternatively, you can set the Tines Webhook URL in the input below', + } +); export const WEBHOOK_URL_HELP = i18n.translate( 'xpack.stackConnectors.security.tines.params.webhookUrlHelp', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts index 6bbaad9b86a0c..299ac1c55bfc5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; @@ -150,6 +150,28 @@ describe('TinesConnector', () => { }); }); + describe('Error handling', () => { + let error: AxiosError; + + beforeEach(() => { + error = new AxiosError(); + }); + + it('should return status text api error', () => { + error.response = { status: 401, statusText: 'Unauthorized' } as AxiosResponse; + // @ts-expect-error protected method + const errorMessage = connector.getResponseErrorMessage(error); + expect(errorMessage).toEqual('API Error: Unauthorized'); + }); + + it('should return original error', () => { + error.toString = () => 'Network Error'; + // @ts-expect-error protected method + const errorMessage = connector.getResponseErrorMessage(error); + expect(errorMessage).toEqual('Network Error'); + }); + }); + describe('getWebhooks', () => { beforeAll(() => { mockRequest.mockReturnValue({ data: { agents: [webhookAgent], meta: { pages: 1 } } }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts index ed98ec382af86..f7e3f4bea1444 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts @@ -126,13 +126,10 @@ export class TinesConnector extends SubActionConnector Date: Tue, 27 Aug 2024 08:50:48 -0400 Subject: [PATCH 30/38] [Rules and Alerting][Stack Monitoring] Quote cluster uuid in global state link sent via alerting rules (#190341) ## Summary Closes https://github.com/elastic/kibana/issues/191250 This PR fixes the URL contained in the Shard size alerting rule when the email body contains the `{{ context.internalFullMessage}}` action variable. The generated URL which triggers a `rison decoder error` `https:///app/monitoring#/elasticsearch/indices/?_g=(cluster_uuid:foobar))` is fixed by adding a pair of single quotes around the cluster UUID `https:///app/monitoring#/elasticsearch/indices/?_g=(cluster_uuid:'foobar'))` Worth noting that this issue doesn't only impact the Shard size rule, but many other rule types, namely: * CPU usage * Disk usage * Memory usage * CCR read exception * ES version mismatch * Kibana version mismatch * Logstash version mismatch * Missing monitoring data * Thread pool search rejections * Thread pool write rejections --------- Co-authored-by: Valentin Crettaz Co-authored-by: Valentin Crettaz --- x-pack/plugins/monitoring/server/rules/base_rule.ts | 2 +- .../server/rules/ccr_read_exceptions_rule.test.ts | 8 ++++---- .../monitoring/server/rules/cpu_usage_rule.test.ts | 8 ++++---- .../monitoring/server/rules/disk_usage_rule.test.ts | 8 ++++---- .../rules/elasticsearch_version_mismatch_rule.test.ts | 4 ++-- .../server/rules/kibana_version_mismatch_rule.test.ts | 4 ++-- .../monitoring/server/rules/large_shard_size_rule.test.ts | 8 ++++---- .../server/rules/logstash_version_mismatch_rule.test.ts | 4 ++-- .../monitoring/server/rules/memory_usage_rule.test.ts | 8 ++++---- .../server/rules/missing_monitoring_data_rule.test.ts | 8 ++++---- .../rules/thread_pool_search_rejections_rule.test.ts | 8 ++++---- .../rules/thread_pool_write_rejections_rule.test.ts | 8 ++++---- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/monitoring/server/rules/base_rule.ts b/x-pack/plugins/monitoring/server/rules/base_rule.ts index f04ca15be27dd..cb8bfcf400d45 100644 --- a/x-pack/plugins/monitoring/server/rules/base_rule.ts +++ b/x-pack/plugins/monitoring/server/rules/base_rule.ts @@ -405,7 +405,7 @@ export class BaseRule { } protected createGlobalStateLink(link: string, clusterUuid: string, ccs?: string) { - const globalState = [`cluster_uuid:${clusterUuid}`]; + const globalState = [`cluster_uuid:'${clusterUuid}'`]; if (ccs) { globalState.push(`ccs:${ccs}`); } diff --git a/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts b/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts index 806c382cb3707..34f9c24b6d49b 100644 --- a/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts @@ -279,9 +279,9 @@ describe('CCRReadExceptionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'BcK-0pmsQniyPQfZuauuXw_remote_cluster_1:.follower_index_1', context: { - internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Verify follower and leader index relationships on the affected remote cluster.`, - action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify follower and leader index relationships on the affected remote cluster.', clusterName, @@ -452,9 +452,9 @@ describe('CCRReadExceptionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'BcK-0pmsQniyPQfZuauuXw_remote_cluster_1:.follower_index_1', context: { - internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, internalShortMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Verify follower and leader index relationships on the affected remote cluster.`, - action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify follower and leader index relationships on the affected remote cluster.', clusterName, diff --git a/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts index 1b107d4031981..0558c2cdf6d33 100644 --- a/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts @@ -185,9 +185,9 @@ describe('CpuUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify CPU level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify CPU level of node.', clusterName, count, @@ -315,9 +315,9 @@ describe('CpuUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify CPU level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify CPU level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts index 5e1c30dce78f6..6e7f66b219e26 100644 --- a/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts @@ -232,9 +232,9 @@ describe('DiskUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify disk usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify disk usage level of node.', clusterName, count, @@ -381,9 +381,9 @@ describe('DiskUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify disk usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/myNodeId?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/myNodeId?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify disk usage level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts index eafb51136fc73..4269c0d6b5a5e 100644 --- a/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts @@ -140,9 +140,9 @@ describe('ElasticsearchVersionMismatchAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all nodes.', - internalFullMessage: `Elasticsearch version mismatch alert is firing for testCluster. Elasticsearch is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Elasticsearch version mismatch alert is firing for testCluster. Elasticsearch is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Elasticsearch version mismatch alert is firing for testCluster. Verify you have the same version across all nodes.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts index 46b777dbee4a2..7a3370c4092a6 100644 --- a/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts @@ -143,9 +143,9 @@ describe('KibanaVersionMismatchRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all instances.', - internalFullMessage: `Kibana version mismatch alert is firing for testCluster. Kibana is running 8.0.0, 7.2.1. [View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Kibana version mismatch alert is firing for testCluster. Kibana is running 8.0.0, 7.2.1. [View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Kibana version mismatch alert is firing for testCluster. Verify you have the same version across all instances.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts b/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts index 0ad6c7687c203..00272030ec4ab 100644 --- a/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts @@ -206,9 +206,9 @@ describe('LargeShardSizeRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123:apm-8.0.0-onboarding-2021.06.30', context: { - internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Large shard size alert is firing for the following index: ${shardIndex}. Investigate indices with large shard sizes.`, - action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Investigate indices with large shard sizes.', clusterName, state: 'firing', @@ -327,9 +327,9 @@ describe('LargeShardSizeRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123:apm-8.0.0-onboarding-2021.06.30', context: { - internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, internalShortMessage: `Large shard size alert is firing for the following index: ${shardIndex}. Investigate indices with large shard sizes.`, - action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Investigate indices with large shard sizes.', clusterName, state: 'firing', diff --git a/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts index 97cbbd2c619a6..7944bd129f2f1 100644 --- a/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts @@ -141,9 +141,9 @@ describe('LogstashVersionMismatchRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all nodes.', - internalFullMessage: `Logstash version mismatch alert is firing for testCluster. Logstash is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Logstash version mismatch alert is firing for testCluster. Logstash is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Logstash version mismatch alert is firing for testCluster. Verify you have the same version across all nodes.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts index c1a8836e293c1..6da0fb751c038 100644 --- a/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts @@ -216,9 +216,9 @@ describe('MemoryUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify memory usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify memory usage level of node.', clusterName, count, @@ -380,9 +380,9 @@ describe('MemoryUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify memory usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify memory usage level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts b/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts index 8bf66a839d6dd..4dd7515e7e33e 100644 --- a/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts @@ -171,11 +171,11 @@ describe('MissingMonitoringDataRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. Verify the node is up and running, then double check the monitoring settings.`, nodes: `node: ${nodeName}`, node: `node: ${nodeName}`, - action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify the node is up and running, then double check the monitoring settings.', clusterName, @@ -287,11 +287,11 @@ describe('MissingMonitoringDataRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. Verify the node is up and running, then double check the monitoring settings.`, nodes: `node: ${nodeName}`, node: `node: ${nodeName}`, - action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, actionPlain: 'Verify the node is up and running, then double check the monitoring settings.', clusterName, diff --git a/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts b/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts index c6602f536a83c..7f93f3cfe6f94 100644 --- a/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts @@ -223,10 +223,10 @@ describe('ThreadpoolSearchRejectionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count: 1, @@ -387,10 +387,10 @@ describe('ThreadpoolSearchRejectionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts b/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts index 163dc2b1a677b..71565b9e75c38 100644 --- a/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts @@ -223,10 +223,10 @@ describe('ThreadpoolWriteRejectionsAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count: 1, @@ -387,10 +387,10 @@ describe('ThreadpoolWriteRejectionsAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count, From 260df9d41298109e2d6f34df4020722ba6ca03dd Mon Sep 17 00:00:00 2001 From: Jamie Tanna Date: Tue, 27 Aug 2024 13:59:30 +0100 Subject: [PATCH 31/38] Revert "Update renovate config (#191304)" (#191495) Reverts elastic/kibana#191304 --- renovate.json | 843 +++++++++++--------------------------------------- 1 file changed, 189 insertions(+), 654 deletions(-) diff --git a/renovate.json b/renovate.json index 233505d4012de..774dce52e3515 100644 --- a/renovate.json +++ b/renovate.json @@ -1,24 +1,9 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - "helpers:pinGitHubActionDigests", - "helpers:pinGitHubActionDigestsToSemver" - ], - "ignorePaths": [ - "**/__fixtures__/**", - "**/fixtures/**" - ], - "enabledManagers": [ - "npm", - "github-actions", - "custom.regex", - "devcontainer" - ], - "baseBranches": [ - "main", - "7.17" - ], + "extends": ["config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver"], + "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], + "enabledManagers": ["npm", "github-actions", "custom.regex", "devcontainer"], + "baseBranches": ["main", "7.17"], "prConcurrentLimit": 0, "prHourlyLimit": 0, "separateMajorMinor": false, @@ -32,51 +17,28 @@ }, "packageRules": [ { - "enabled": false, - "matchDepNames": [ - "/.*/" - ] + "matchDepPatterns": [".*"], + "enabled": false }, { "groupName": "devcontainer", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "backport:current-major" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip", "backport:current-major"], "enabled": true, - "matchManagers": [ - "devcontainer" - ] + "matchManagers": ["devcontainer"] }, { "groupName": "chainguard", - "matchPackageNames": [ - "docker.elastic.co/wolfi/chainguard-base" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "enabled": true }, { "groupName": "operations actions", - "matchManagers": [ - "github-actions" - ], + "matchManagers": ["github-actions"], "matchPackageNames": [ "actions/checkout", "elastic/github-actions/project-assigner", @@ -85,367 +47,168 @@ "sergeysova/jq-action", "sourenlouv/backport" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "backport:all-open", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "enabled": true }, { "groupName": "@elastic/charts", - "matchDepNames": [ - "@elastic/charts" - ], - "reviewers": [ - "team:visualizations", - "markov00", - "nickofthyme" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "Team:Visualizations" - ], + "matchDepNames": ["@elastic/charts"], + "reviewers": ["team:visualizations", "markov00", "nickofthyme"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "Team:Visualizations"], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": [ - "@elastic/elasticsearch" - ], - "reviewers": [ - "team:kibana-operations", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "Team:Operations", - "Team:Core" - ], + "matchDepNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "Team:Operations", "Team:Core"], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": [ - "@elastic/elasticsearch" - ], - "reviewers": [ - "team:kibana-operations", - "team:kibana-core" - ], - "matchBaseBranches": [ - "7.17" - ], - "labels": [ - "release_note:skip", - "Team:Operations", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["7.17"], + "labels": ["release_note:skip", "Team:Operations", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "LaunchDarkly", - "matchDepNames": [ - "launchdarkly-js-client-sdk", - "@launchdarkly/node-server-sdk", - "launchdarkly/find-code-references" - ], - "reviewers": [ - "team:kibana-security", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Security", - "Team:Core", - "backport:prev-minor" - ], + "matchDepNames": ["launchdarkly-js-client-sdk", "@launchdarkly/node-server-sdk", "launchdarkly/find-code-references"], + "reviewers": ["team:kibana-security", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Security", "Team:Core", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "APM", - "matchDepNames": [ - "elastic-apm-node", - "@elastic/apm-rum", - "@elastic/apm-rum-react" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["elastic-apm-node", "@elastic/apm-rum", "@elastic/apm-rum-react"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "@elastic/ebt", - "matchDepNames": [ - "@elastic/ebt" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@elastic/ebt"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "ansi-regex", - "matchDepNames": [ - "ansi-regex" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["ansi-regex"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenAPI Spec", - "matchDepNames": [ - "@redocly/cli" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@redocly/cli"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "babel", - "matchDepNames": [ - "@types/babel__core", - "/^@babel/", - "/^babel-plugin/" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["@types/babel__core"], + "matchDepPatterns": ["^@babel", "^babel-plugin"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "typescript", - "matchDepNames": [ - "typescript", - "@types/jsdom" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["typescript", "@types/jsdom"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "prettier", - "matchDepNames": [ - "prettier", - "eslint-plugin-prettier", - "eslint-config-prettier" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["prettier", "eslint-plugin-prettier", "eslint-config-prettier"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<3.0", "enabled": true }, { "groupName": "typescript-eslint", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepPatterns": ["^@typescript-eslint"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/^@typescript-eslint/" - ] + "enabled": true }, { "groupName": "eslint-plugin-depend", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepPatterns": ["eslint-plugin-depend"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/eslint-plugin-depend/" - ] + "enabled": true }, { "groupName": "polyfills", - "matchDepNames": [ - "core-js", - "/polyfill/" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["core-js"], + "matchDepPatterns": ["polyfill"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CLI tooling", - "matchDepNames": [ - "listr2" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "backport:all-open", - "release_note:skip" - ], + "matchDepNames": ["listr2"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "vega related modules", - "matchDepNames": [ - "vega", - "vega-lite", - "vega-schema-url-parser", - "vega-tooltip" - ], - "reviewers": [ - "team:kibana-visualizations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Feature:Vega", - "Team:Visualizations" - ], + "matchDepNames": ["vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip"], + "reviewers": ["team:kibana-visualizations"], + "matchBaseBranches": ["main"], + "labels": ["Feature:Vega", "Team:Visualizations"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "cypress", - "reviewers": [ - "Team:apm", - "Team: SecuritySolution" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "buildkite-ci", - "ci:all-cypress-suites" - ], + "matchDepPatterns": ["cypress"], + "reviewers": ["Team:apm", "Team: SecuritySolution"], + "matchBaseBranches": ["main"], + "labels": ["buildkite-ci", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/cypress/" - ] + "enabled": true }, { "groupName": "security solution modules", - "matchDepNames": [ - "zod", - "langchain" - ], - "reviewers": [ - "Team: SecuritySolution" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: SecuritySolution" - ], + "matchDepNames": ["zod", "langchain"], + "reviewers": ["Team: SecuritySolution"], + "matchBaseBranches": ["main"], + "labels": ["Team: SecuritySolution"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -463,17 +226,9 @@ "@types/xml-crypto", "@kayahr/text-encoding" ], - "reviewers": [ - "team:kibana-security" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Security", - "release_note:skip", - "backport:all-open" - ], + "reviewers": ["team:kibana-security"], + "matchBaseBranches": ["main"], + "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -483,17 +238,9 @@ "github/codeql-action/analyze", "github/codeql-action/init" ], - "reviewers": [ - "team:kibana-security" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Security", - "release_note:skip", - "backport:all-open" - ], + "reviewers": ["team:kibana-security"], + "matchBaseBranches": ["main"], + "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -507,54 +254,27 @@ "ms-chromium-edge-driver", "selenium-webdriver" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "scss", - "matchDepNames": [ - "sass-embedded" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "backport:all-open" - ], + "matchDepNames": ["sass-embedded"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "minify", - "matchDepNames": [ - "gulp-terser", - "terser" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["gulp-terser", "terser"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -568,16 +288,9 @@ "@testing-library/user-event", "@types/testing-library__jest-dom" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -599,68 +312,36 @@ "jest-runtime", "jest-snapshot" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@storybook", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "ci:build-storybooks", - "backport:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "matchDepPatterns": ["^@storybook"], + "excludeDepNames": ["@storybook/testing-react"], + "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<7.0", - "enabled": true, - "matchDepNames": [ - "/^@storybook/", - "!@storybook/testing-react" - ] + "enabled": true }, { "groupName": "@storybook/testing-react", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "matchDepNames": [ - "@storybook/testing-react" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "ci:build-storybooks", - "backport:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "matchDepNames": ["@storybook/testing-react"], + "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<2.0", "enabled": true }, { "groupName": "react-query", - "matchDepNames": [ - "@tanstack/react-query", - "@tanstack/react-query-devtools" - ], + "matchDepNames": ["@tanstack/react-query", "@tanstack/react-query-devtools"], "reviewers": [ "team:response-ops", "team:kibana-cloud-security-posture", @@ -669,43 +350,23 @@ "team:awp-platform", "team:security-onboarding-and-lifecycle-mgt" ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "react-hook-form", - "matchDepNames": [ - "react-hook-form" - ], - "reviewers": [ - "team:security-asset-management", - "team:uptime" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchDepNames": ["react-hook-form"], + "reviewers": ["team:security-asset-management", "team:uptime"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "redux", - "matchDepNames": [ - "redux", - "react-redux" - ], + "matchDepNames": ["redux", "react-redux"], "reviewers": [ "team:search-kibana", "team:kibana-presentation", @@ -714,241 +375,115 @@ "team:kibana-gis", "team:security-solution" ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Profiling", - "matchDepNames": [ - "peggy", - "@types/dagre" - ], - "reviewers": [ - "team:obs-ux-infra_services-team" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["peggy", "@types/dagre"], + "reviewers": ["team:obs-ux-infra_services-team"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "TTY Output", - "matchDepNames": [ - "xterm", - "byte-size", - "@types/byte-size" - ], - "reviewers": [ - "team:sec-cloudnative-integrations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: AWP: Visualization", - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["xterm", "byte-size", "@types/byte-size"], + "reviewers": ["team:sec-cloudnative-integrations"], + "matchBaseBranches": ["main"], + "labels": ["Team: AWP: Visualization", "release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Cloud Defend", - "matchDepNames": [ - "monaco-yaml" - ], - "reviewers": [ - "team:sec-cloudnative-integrations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: Cloud Native Integrations", - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["monaco-yaml"], + "reviewers": ["team:sec-cloudnative-integrations"], + "matchBaseBranches": ["main"], + "labels": ["Team: Cloud Native Integrations", "release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "JSON Web Token", - "matchDepNames": [ - "jsonwebtoken" - ], - "reviewers": [ - "team:response-ops", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:all-open" - ], + "matchDepNames": ["jsonwebtoken"], + "reviewers": ["team:response-ops", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "XState", - "matchDepNames": [ - "xstate", - "@xstate/{/,}**" - ], - "reviewers": [ - "team:obs-ux-logs-team" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Obs UX Logs", - "release_note:skip" - ], + "matchDepNames": ["xstate"], + "matchDepPrefixes": ["@xstate/"], + "reviewers": ["team:obs-ux-logs-team"], + "matchBaseBranches": ["main"], + "labels": ["Team:Obs UX Logs", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenTelemetry modules", - "reviewers": [ - "team:stack-monitoring" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Monitoring" - ], + "matchDepPrefixes": ["@opentelemetry/"], + "reviewers": ["team:stack-monitoring"], + "matchBaseBranches": ["main"], + "labels": ["Team:Monitoring"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "@opentelemetry/{/,}**" - ] + "enabled": true }, { "groupName": "csp", - "matchDepNames": [ - "content-security-policy-parser" - ], - "reviewers": [ - "team:kibana-security", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:serverless-test-all" - ], + "matchDepNames": ["content-security-policy-parser"], + "reviewers": ["team:kibana-security", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:serverless-test-all"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "AlertingEmails", - "matchDepNames": [ - "nodemailer" - ], - "reviewers": [ - "team:response-ops" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:prev-minor" - ], + "matchDepNames": ["nodemailer"], + "reviewers": ["team:response-ops"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Kibana ES|QL Team", - "matchDepNames": [ - "recast" - ], - "reviewers": [ - "team:kibana-esql" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:ESQL", - "release_note:skip" - ], + "matchDepNames": ["recast"], + "reviewers": ["team:kibana-esql"], + "matchBaseBranches": ["main"], + "labels": ["Team:ESQL", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "MSW", - "matchPackageNames": [ - "msw" - ], - "reviewers": [ - "team:kibana-cloud-security-posture" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: Cloud Security", - "release_note:skip", - "backport:skip" - ], + "matchPackageNames": ["msw"], + "reviewers": ["team:kibana-cloud-security-posture"], + "matchBaseBranches": ["main"], + "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], "enabled": true }, { "groupName": "re2js", - "matchDepNames": [ - "re2js" - ], - "reviewers": [ - "team:visualizations", - "dej611" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:all-open", - "Team:Visualizations" - ], + "matchDepNames": ["re2js"], + "reviewers": ["team:visualizations", "dej611"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:all-open", "Team:Visualizations"], "enabled": true }, { "groupName": "Serve swagger docs", - "matchDepNames": [ - "express", - "swagger-jsdoc", - "swagger-ui-express" - ], - "reviewers": [ - "team:obs-entities" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "team:obs-entities" - ], + "matchDepNames": ["express", "swagger-jsdoc", "swagger-ui-express"], + "reviewers": ["team:obs-entities"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "team:obs-entities"], "enabled": true } ], @@ -977,4 +512,4 @@ "datasourceTemplate": "docker" } ] -} \ No newline at end of file +} From 90f2eb3a0858c390c713be418464e0c63ed2b2d6 Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:56:04 +0200 Subject: [PATCH 32/38] Expose privilege API client to spaces (#189819) ## Summary Expose privilege API client to be injected into the spaces app, to facilitate new spaces UX --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../security/plugin_types_public/index.ts | 2 ++ .../authorization/authorization_service.ts | 6 ++++++ .../src/privileges/index.ts | 9 ++++++++ .../src/privileges/privileges_api_client.ts | 21 +++++++++++++++++++ .../plugin_types_public/tsconfig.json | 1 + .../public/authentication/index.mock.ts | 6 ++++++ .../authorization/authorization_service.ts | 6 +++++- .../security/public/management/index.ts | 2 +- .../security/public/management/roles/index.ts | 1 + .../management/roles/privileges_api_client.ts | 11 +++++----- .../plugins/security/public/plugin.test.tsx | 9 +++++++- .../management/management_service.test.ts | 3 +++ .../public/management/management_service.tsx | 8 ++++++- .../management/spaces_management_app.test.tsx | 2 ++ .../management/spaces_management_app.tsx | 6 +++++- x-pack/plugins/spaces/public/plugin.tsx | 13 ++++++++++++ 16 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 x-pack/packages/security/plugin_types_public/src/privileges/index.ts create mode 100644 x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts diff --git a/x-pack/packages/security/plugin_types_public/index.ts b/x-pack/packages/security/plugin_types_public/index.ts index 0b326ce2ee664..a2a6f4ea6a3ee 100644 --- a/x-pack/packages/security/plugin_types_public/index.ts +++ b/x-pack/packages/security/plugin_types_public/index.ts @@ -17,3 +17,5 @@ export type { UserProfileAPIClient, } from './src/user_profile'; export type { RolePutPayload, RolesAPIClient } from './src/roles'; +export { PrivilegesAPIClientPublicContract } from './src/privileges'; +export type { PrivilegesAPIClientGetAllArgs } from './src/privileges'; diff --git a/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts b/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts index 5ad462f8c2aa1..f04acf8020b24 100644 --- a/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts +++ b/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts @@ -6,6 +6,7 @@ */ import type { RolesAPIClient } from '../roles'; +import type { PrivilegesAPIClientPublicContract } from '../privileges'; export interface AuthorizationServiceSetup { /** @@ -17,6 +18,11 @@ export interface AuthorizationServiceSetup { * A set of methods to work with Kibana user roles. */ roles: RolesAPIClient; + + /** + * A set of methods to work with Kibana role privileges + */ + privileges: PrivilegesAPIClientPublicContract; } /** diff --git a/x-pack/packages/security/plugin_types_public/src/privileges/index.ts b/x-pack/packages/security/plugin_types_public/src/privileges/index.ts new file mode 100644 index 0000000000000..b8d111a0c79fe --- /dev/null +++ b/x-pack/packages/security/plugin_types_public/src/privileges/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 { PrivilegesAPIClientPublicContract } from './privileges_api_client'; +export type { PrivilegesAPIClientGetAllArgs } from './privileges_api_client'; diff --git a/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts b/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts new file mode 100644 index 0000000000000..e3a97398db7a3 --- /dev/null +++ b/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts @@ -0,0 +1,21 @@ +/* + * 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 type { RawKibanaPrivileges } from '@kbn/security-authorization-core'; + +export interface PrivilegesAPIClientGetAllArgs { + includeActions: boolean; + /* + * respectLicenseLevel is an internal optional parameter solely for getting all sub-feature + * privileges to use in the UI. It is not meant for any other use. + */ + respectLicenseLevel: boolean; +} +// TODO: Eyo include the proper return types for contract +export abstract class PrivilegesAPIClientPublicContract { + abstract getAll(args: PrivilegesAPIClientGetAllArgs): Promise; +} diff --git a/x-pack/packages/security/plugin_types_public/tsconfig.json b/x-pack/packages/security/plugin_types_public/tsconfig.json index 6779851e86367..5c97e25656ecf 100644 --- a/x-pack/packages/security/plugin_types_public/tsconfig.json +++ b/x-pack/packages/security/plugin_types_public/tsconfig.json @@ -14,5 +14,6 @@ "@kbn/core-user-profile-common", "@kbn/security-plugin-types-common", "@kbn/core-security-common", + "@kbn/security-authorization-core" ] } diff --git a/x-pack/plugins/security/public/authentication/index.mock.ts b/x-pack/plugins/security/public/authentication/index.mock.ts index 491b5b82e946a..166583b1274cb 100644 --- a/x-pack/plugins/security/public/authentication/index.mock.ts +++ b/x-pack/plugins/security/public/authentication/index.mock.ts @@ -32,6 +32,9 @@ export const authorizationMock = { deleteRole: jest.fn(), saveRole: jest.fn(), }, + privileges: { + getAll: jest.fn(), + }, }), createStart: (): jest.Mocked => ({ isRoleManagementEnabled: jest.fn(), @@ -41,5 +44,8 @@ export const authorizationMock = { deleteRole: jest.fn(), saveRole: jest.fn(), }, + privileges: { + getAll: jest.fn(), + }, }), }; diff --git a/x-pack/plugins/security/public/authorization/authorization_service.ts b/x-pack/plugins/security/public/authorization/authorization_service.ts index 6e0af055a6cda..c650d381be1af 100644 --- a/x-pack/plugins/security/public/authorization/authorization_service.ts +++ b/x-pack/plugins/security/public/authorization/authorization_service.ts @@ -9,7 +9,7 @@ import type { HttpStart } from '@kbn/core/public'; import type { AuthorizationServiceSetup } from '@kbn/security-plugin-types-public'; import type { ConfigType } from '../config'; -import { RolesAPIClient } from '../management'; +import { PrivilegesAPIClient, RolesAPIClient } from '../management'; interface SetupParams { config: ConfigType; @@ -20,6 +20,7 @@ export class AuthorizationService { public setup({ config, http }: SetupParams): AuthorizationServiceSetup { const isRoleManagementEnabled = () => config.roleManagementEnabled; const rolesAPIClient = new RolesAPIClient(http); + const privilegesAPIClient = new PrivilegesAPIClient(http); return { isRoleManagementEnabled, @@ -29,6 +30,9 @@ export class AuthorizationService { deleteRole: rolesAPIClient.deleteRole, saveRole: rolesAPIClient.saveRole, }, + privileges: { + getAll: privilegesAPIClient.getAll.bind(privilegesAPIClient), + }, }; } } diff --git a/x-pack/plugins/security/public/management/index.ts b/x-pack/plugins/security/public/management/index.ts index a47475485896d..2c1708f1c9bb0 100644 --- a/x-pack/plugins/security/public/management/index.ts +++ b/x-pack/plugins/security/public/management/index.ts @@ -7,4 +7,4 @@ export { ManagementService } from './management_service'; export { UserAPIClient } from './users/user_api_client'; -export { RolesAPIClient } from './roles'; +export { RolesAPIClient, PrivilegesAPIClient } from './roles'; diff --git a/x-pack/plugins/security/public/management/roles/index.ts b/x-pack/plugins/security/public/management/roles/index.ts index 86d5990761d4d..258fd1ee558be 100644 --- a/x-pack/plugins/security/public/management/roles/index.ts +++ b/x-pack/plugins/security/public/management/roles/index.ts @@ -7,3 +7,4 @@ export { rolesManagementApp } from './roles_management_app'; export { RolesAPIClient } from './roles_api_client'; +export { PrivilegesAPIClient } from './privileges_api_client'; diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts index 54c8992698978..5032871c41fa6 100644 --- a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts +++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts @@ -7,16 +7,15 @@ import type { HttpStart } from '@kbn/core/public'; import type { RawKibanaPrivileges } from '@kbn/security-authorization-core'; +import { PrivilegesAPIClientPublicContract } from '@kbn/security-plugin-types-public'; import type { BuiltinESPrivileges } from '../../../common/model'; -export class PrivilegesAPIClient { - constructor(private readonly http: HttpStart) {} +export class PrivilegesAPIClient extends PrivilegesAPIClientPublicContract { + constructor(private readonly http: HttpStart) { + super(); + } - /* - * respectLicenseLevel is an internal optional parameter soley for getting all sub-feature - * privilieges to use in the UI. It is not meant for any other use. - */ async getAll({ includeActions, respectLicenseLevel = true, diff --git a/x-pack/plugins/security/public/plugin.test.tsx b/x-pack/plugins/security/public/plugin.test.tsx index 433e1981e9ce9..336a42a1fd324 100644 --- a/x-pack/plugins/security/public/plugin.test.tsx +++ b/x-pack/plugins/security/public/plugin.test.tsx @@ -40,7 +40,11 @@ describe('Security Plugin', () => { }) ).toEqual({ authc: { getCurrentUser: expect.any(Function), areAPIKeysEnabled: expect.any(Function) }, - authz: { isRoleManagementEnabled: expect.any(Function), roles: expect.any(Object) }, + authz: { + isRoleManagementEnabled: expect.any(Function), + roles: expect.any(Object), + privileges: expect.any(Object), + }, license: { isLicenseAvailable: expect.any(Function), getLicenseType: expect.any(Function), @@ -129,6 +133,9 @@ describe('Security Plugin', () => { }, "authz": Object { "isRoleManagementEnabled": [Function], + "privileges": Object { + "getAll": [Function], + }, "roles": Object { "deleteRole": [Function], "getRole": [Function], diff --git a/x-pack/plugins/spaces/public/management/management_service.test.ts b/x-pack/plugins/spaces/public/management/management_service.test.ts index e01ddd8db9ae2..5f97515171518 100644 --- a/x-pack/plugins/spaces/public/management/management_service.test.ts +++ b/x-pack/plugins/spaces/public/management/management_service.test.ts @@ -42,6 +42,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: getRolesAPIClientMock, + getPrivilegesAPIClient: jest.fn(), eventTracker, }); @@ -63,6 +64,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: getRolesAPIClientMock, + getPrivilegesAPIClient: jest.fn(), eventTracker, }); }); @@ -85,6 +87,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }); diff --git a/x-pack/plugins/spaces/public/management/management_service.tsx b/x-pack/plugins/spaces/public/management/management_service.tsx index 9bc94e70b83f5..b186135d88e05 100644 --- a/x-pack/plugins/spaces/public/management/management_service.tsx +++ b/x-pack/plugins/spaces/public/management/management_service.tsx @@ -7,7 +7,10 @@ import type { StartServicesAccessor } from '@kbn/core/public'; import type { ManagementApp, ManagementSetup } from '@kbn/management-plugin/public'; -import type { RolesAPIClient } from '@kbn/security-plugin-types-public'; +import type { + PrivilegesAPIClientPublicContract, + RolesAPIClient, +} from '@kbn/security-plugin-types-public'; import { spacesManagementApp } from './spaces_management_app'; import type { EventTracker } from '../analytics'; @@ -22,6 +25,7 @@ interface SetupDeps { config: ConfigType; getRolesAPIClient: () => Promise; eventTracker: EventTracker; + getPrivilegesAPIClient: () => Promise; } export class ManagementService { @@ -34,6 +38,7 @@ export class ManagementService { config, getRolesAPIClient, eventTracker, + getPrivilegesAPIClient, }: SetupDeps) { this.registeredSpacesManagementApp = management.sections.section.kibana.registerApp( spacesManagementApp.create({ @@ -42,6 +47,7 @@ export class ManagementService { config, getRolesAPIClient, eventTracker, + getPrivilegesAPIClient, }) ); } diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index 2415d603086e9..61619c499181c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -57,6 +57,7 @@ async function mountApp(basePath: string, pathname: string, spaceId?: string) { getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}], config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }) .mount({ @@ -79,6 +80,7 @@ describe('spacesManagementApp', () => { getStartServices: coreMock.createSetup().getStartServices as any, config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }) ).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index 9883286122653..40532a7259521 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -14,7 +14,10 @@ import { i18n } from '@kbn/i18n'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; -import type { RolesAPIClient } from '@kbn/security-plugin-types-public'; +import type { + PrivilegesAPIClientPublicContract, + RolesAPIClient, +} from '@kbn/security-plugin-types-public'; import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { Route, Router, Routes } from '@kbn/shared-ux-router'; @@ -30,6 +33,7 @@ interface CreateParams { config: ConfigType; getRolesAPIClient: () => Promise; eventTracker: EventTracker; + getPrivilegesAPIClient: () => Promise; } export const spacesManagementApp = Object.freeze({ diff --git a/x-pack/plugins/spaces/public/plugin.tsx b/x-pack/plugins/spaces/public/plugin.tsx index b07595618c3cc..31ba324b926f3 100644 --- a/x-pack/plugins/spaces/public/plugin.tsx +++ b/x-pack/plugins/spaces/public/plugin.tsx @@ -95,6 +95,18 @@ export class SpacesPlugin implements Plugin { + const { security } = await core.plugins.onSetup<{ security: SecurityPluginStart }>( + 'security' + ); + + if (!security.found) { + throw new Error('Security plugin is not available as runtime dependency.'); + } + + return security.contract.authz.privileges; + }; + if (plugins.home) { plugins.home.featureCatalogue.register(createSpacesFeatureCatalogueEntry()); } @@ -108,6 +120,7 @@ export class SpacesPlugin implements Plugin Date: Tue, 27 Aug 2024 15:07:00 +0100 Subject: [PATCH 33/38] [ObsUX][Infra] Fix redirect to other apps from node details (#191294) Closes https://github.com/elastic/kibana/issues/190510 The return button in the asset details failed to return to another app ##### How to test From apm service details, navigate to Infrastructure tab, click in one of the nodes that would navigate to the node details page, when clicking the Return button it should redirect back to APM/Services/{serviceName}/Infrastructure https://github.com/user-attachments/assets/07555fa6-246b-43c3-81bf-592b550713a0 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../components/metrics_node_details_link.tsx | 19 ++--- .../public/hooks/use_kibana.tsx | 4 +- .../link_to/use_node_details_redirect.ts | 80 +++++++++++++------ .../metrics_data_access/tsconfig.json | 3 +- 4 files changed, 70 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx b/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx index 10ecf3dc42626..e683d1708907b 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx @@ -8,7 +8,6 @@ import { parse } from '@kbn/datemath'; import { EuiLink } from '@elastic/eui'; import React from 'react'; -import { useLinkProps } from '@kbn/observability-shared-plugin/public'; import type { InventoryItemType } from '../../../../../common/inventory_models/types'; import { useNodeDetailsRedirect } from '../../../../pages/link_to/use_node_details_redirect'; @@ -28,16 +27,14 @@ export const MetricsNodeDetailsLink = ({ timerange, }: MetricsNodeDetailsLinkProps) => { const { getNodeDetailUrl } = useNodeDetailsRedirect(); - const linkProps = useLinkProps( - getNodeDetailUrl({ - nodeType, - nodeId: id, - search: { - from: parse(timerange.from)?.valueOf(), - to: parse(timerange.to)?.valueOf(), - }, - }) - ); + const linkProps = getNodeDetailUrl({ + nodeType, + nodeId: id, + search: { + from: parse(timerange.from)?.valueOf(), + to: parse(timerange.to)?.valueOf(), + }, + }); return ( diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx b/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx index c99caa3f4c266..423460b383549 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx @@ -12,12 +12,14 @@ import { KibanaReactContextValue, useKibana, } from '@kbn/kibana-react-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; -export type PluginKibanaContextValue = CoreStart; +export type PluginKibanaContextValue = CoreStart & { share?: SharePluginStart }; export const createKibanaContextForPlugin = (core: CoreStart) => createKibanaReactContext({ ...core, + share: {} as SharePluginStart, }); export const useKibanaContextForPlugin = diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts b/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts index 7d9c813f97479..aea3042d79ae2 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts @@ -7,8 +7,13 @@ import { useCallback } from 'react'; import { useLocation } from 'react-router-dom'; -import type { LinkDescriptor } from '@kbn/observability-shared-plugin/public'; import useObservable from 'react-use/lib/useObservable'; +import { RouterLinkProps, getRouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; +import { Search } from 'history'; +import { + type AssetDetailsLocatorParams, + ASSET_DETAILS_LOCATOR_ID, +} from '@kbn/observability-shared-plugin/common'; import type { InventoryItemType } from '../../../common/inventory_models/types'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; @@ -18,15 +23,24 @@ interface QueryParams { assetName?: string; } +export interface RouteState { + originAppId: string; + originPathname: string; + originSearch?: Search; +} + export const useNodeDetailsRedirect = () => { const location = useLocation(); const { services: { application: { currentAppId$ }, + share, }, } = useKibanaContextForPlugin(); const appId = useObservable(currentAppId$); + const locator = share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID); + const getNodeDetailUrl = useCallback( ({ nodeType, @@ -36,34 +50,54 @@ export const useNodeDetailsRedirect = () => { nodeType: InventoryItemType; nodeId: string; search: QueryParams; - }): LinkDescriptor => { + }): RouterLinkProps => { const { to, from, ...rest } = search; - - return { - app: 'metrics', - pathname: `link-to/${nodeType}-detail/${nodeId}`, - search: { - ...rest, - ...(to && from - ? { - to: `${to}`, - from: `${from}`, - } - : undefined), - // While we don't have a shared state between all page in infra, this makes it possible to restore a page state when returning to the previous route - ...(location.search || location.pathname + const queryParams = { + nodeDetails: + Object.keys(rest).length > 0 ? { - state: JSON.stringify({ - originAppId: appId, - originSearch: location.search, - originPathname: location.pathname, - }), + ...rest, + dateRange: { + from: from ? new Date(from).toISOString() : undefined, + to: to ? new Date(to).toISOString() : undefined, + }, } - : undefined), + : {}, + _a: { + time: { + ...(from ? { from: new Date(from).toISOString() } : undefined), + ...(to ? { to: new Date(to).toISOString() } : undefined), + interval: '>=1m', + }, }, }; + + const nodeDetailsLocatorParams = { + ...queryParams, + assetType: nodeType, + assetId: nodeId, + state: { + ...(location.state ?? {}), + ...(location.key + ? ({ + originAppId: appId, + originSearch: location.search, + originPathname: location.pathname, + } as RouteState) + : {}), + }, + }; + + const nodeDetailsLinkProps = getRouterLinkProps({ + href: locator?.getRedirectUrl(nodeDetailsLocatorParams), + onClick: () => { + locator?.navigate(nodeDetailsLocatorParams, { replace: false }); + }, + }); + + return nodeDetailsLinkProps; }, - [location.pathname, appId, location.search] + [appId, location.key, location.pathname, location.search, location.state, locator] ); return { getNodeDetailUrl }; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json b/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json index 39ca16361f6cd..0c2c471a6bf77 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json +++ b/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json @@ -35,6 +35,7 @@ "@kbn/core-http-request-handler-context-server", "@kbn/lens-embeddable-utils", "@kbn/react-kibana-context-render", - "@kbn/react-kibana-context-theme" + "@kbn/react-kibana-context-theme", + "@kbn/router-utils" ] } From fd312e30dbdac779ebda11af1a8dd9a84b63a092 Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:17:08 +0200 Subject: [PATCH 34/38] Extract Kibana Privilege Feature table into package (#189871) ## Summary This PR extracts the kibana privilege component into a package, to support the work that's been done to integrate role privilege selection within the newly improved spaces administration app, and is the last in the series of PR to make this possible. Without this undertaken we would be creating cyclic dependency between the security and spaces plugin, the image below provides a visual representation on how this PR resolves the aforementioned issue; ![image](https://github.com/user-attachments/assets/3de515a4-3f8b-4708-99af-d175d5bab282)[^legend] [^legend]: item marked in blue is the package created in this PR. This particular component, alongside the components that it's composed of will now be housed in `@kbn/security-ui-components` (P.S. I'm not too entirely sure about the naming, suggestions welcome). --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + package.json | 1 + tsconfig.base.json | 2 ++ .../packages/security/ui_components/README.md | 3 +++ .../packages/security/ui_components/index.ts | 13 ++++++++++ .../security/ui_components/jest.config.js | 15 +++++++++++ .../security/ui_components/kibana.jsonc | 5 ++++ .../security/ui_components/package.json | 6 +++++ .../security/ui_components/src}/constants.ts | 0 .../__fixtures__/index.ts | 0 .../change_all_privileges.scss | 0 .../change_all_privileges.tsx | 0 .../components}/feature_table_cell.scss | 0 .../components}/feature_table_cell.test.tsx | 0 .../components}/feature_table_cell.tsx | 0 .../components}/index.ts | 0 .../feature_table.scss | 0 .../feature_table.test.tsx | 2 +- .../kibana_privilege_table}/feature_table.tsx | 2 +- .../feature_table_expanded_row.test.tsx | 2 +- .../feature_table_expanded_row.tsx | 0 .../src/kibana_privilege_table}/index.ts | 1 + .../sub_feature_form.test.tsx | 0 .../sub_feature_form.tsx | 0 .../src}/privilege_form_calculator/index.ts | 0 .../privilege_form_calculator.test.ts | 2 +- .../privilege_form_calculator.ts | 0 .../security/ui_components/tsconfig.json | 18 +++++++++++++ .../roles/edit_role/edit_role_page.tsx | 4 ++- .../privilege_summary/__fixtures__/index.ts | 2 +- .../privilege_summary_table.tsx | 2 +- .../privilege_selector.tsx | 6 ++--- .../simple_privilege_section.tsx | 26 ++++++++++--------- .../privilege_display.tsx | 5 ++-- .../privilege_space_form.test.tsx | 4 +-- .../privilege_space_form.tsx | 17 +++++++----- .../privilege_space_table.test.tsx | 2 +- .../privilege_space_table.tsx | 7 +++-- .../space_aware_privilege_section.tsx | 2 +- x-pack/plugins/security/tsconfig.json | 1 + yarn.lock | 4 +++ 41 files changed, 116 insertions(+), 39 deletions(-) create mode 100644 x-pack/packages/security/ui_components/README.md create mode 100644 x-pack/packages/security/ui_components/index.ts create mode 100644 x-pack/packages/security/ui_components/jest.config.js create mode 100644 x-pack/packages/security/ui_components/kibana.jsonc create mode 100644 x-pack/packages/security/ui_components/package.json rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana => packages/security/ui_components/src}/constants.ts (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/__fixtures__/index.ts (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/change_all_privileges.scss (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/change_all_privileges.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell => packages/security/ui_components/src/kibana_privilege_table/components}/feature_table_cell.scss (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell => packages/security/ui_components/src/kibana_privilege_table/components}/feature_table_cell.test.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell => packages/security/ui_components/src/kibana_privilege_table/components}/feature_table_cell.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell => packages/security/ui_components/src/kibana_privilege_table/components}/index.ts (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/feature_table.scss (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/feature_table.test.tsx (99%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/feature_table.tsx (99%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/feature_table_expanded_row.test.tsx (99%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/feature_table_expanded_row.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/index.ts (86%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/sub_feature_form.test.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table => packages/security/ui_components/src/kibana_privilege_table}/sub_feature_form.tsx (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana => packages/security/ui_components/src}/privilege_form_calculator/index.ts (100%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana => packages/security/ui_components/src}/privilege_form_calculator/privilege_form_calculator.test.ts (99%) rename x-pack/{plugins/security/public/management/roles/edit_role/privileges/kibana => packages/security/ui_components/src}/privilege_form_calculator/privilege_form_calculator.ts (100%) create mode 100644 x-pack/packages/security/ui_components/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b74db49fc30ea..79a8000fe2f68 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -774,6 +774,7 @@ x-pack/packages/security-solution/side_nav @elastic/security-threat-hunting-expl x-pack/packages/security-solution/storybook/config @elastic/security-threat-hunting-explore x-pack/packages/security-solution/upselling @elastic/security-threat-hunting-explore x-pack/test/security_functional/plugins/test_endpoints @elastic/kibana-security +x-pack/packages/security/ui_components @elastic/kibana-security packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine x-pack/packages/security-solution/data_table @elastic/security-threat-hunting-investigations packages/kbn-securitysolution-ecs @elastic/security-threat-hunting-explore diff --git a/package.json b/package.json index 78d2e97408fa0..95ad8e437e9d3 100644 --- a/package.json +++ b/package.json @@ -790,6 +790,7 @@ "@kbn/security-solution-storybook-config": "link:x-pack/packages/security-solution/storybook/config", "@kbn/security-solution-upselling": "link:x-pack/packages/security-solution/upselling", "@kbn/security-test-endpoints-plugin": "link:x-pack/test/security_functional/plugins/test_endpoints", + "@kbn/security-ui-components": "link:x-pack/packages/security/ui_components", "@kbn/securitysolution-autocomplete": "link:packages/kbn-securitysolution-autocomplete", "@kbn/securitysolution-data-table": "link:x-pack/packages/security-solution/data_table", "@kbn/securitysolution-ecs": "link:packages/kbn-securitysolution-ecs", diff --git a/tsconfig.base.json b/tsconfig.base.json index d6b0733743929..860e8dae3d523 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1542,6 +1542,8 @@ "@kbn/security-solution-upselling/*": ["x-pack/packages/security-solution/upselling/*"], "@kbn/security-test-endpoints-plugin": ["x-pack/test/security_functional/plugins/test_endpoints"], "@kbn/security-test-endpoints-plugin/*": ["x-pack/test/security_functional/plugins/test_endpoints/*"], + "@kbn/security-ui-components": ["x-pack/packages/security/ui_components"], + "@kbn/security-ui-components/*": ["x-pack/packages/security/ui_components/*"], "@kbn/securitysolution-autocomplete": ["packages/kbn-securitysolution-autocomplete"], "@kbn/securitysolution-autocomplete/*": ["packages/kbn-securitysolution-autocomplete/*"], "@kbn/securitysolution-data-table": ["x-pack/packages/security-solution/data_table"], diff --git a/x-pack/packages/security/ui_components/README.md b/x-pack/packages/security/ui_components/README.md new file mode 100644 index 0000000000000..dd5ee7d160285 --- /dev/null +++ b/x-pack/packages/security/ui_components/README.md @@ -0,0 +1,3 @@ +# @kbn/security-ui-components + +Contains stateless components for RBAC administration within Kibana. diff --git a/x-pack/packages/security/ui_components/index.ts b/x-pack/packages/security/ui_components/index.ts new file mode 100644 index 0000000000000..3730109d9c0f8 --- /dev/null +++ b/x-pack/packages/security/ui_components/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { + FeatureTable as KibanaPrivilegeTable, + FeatureTableCell, +} from './src/kibana_privilege_table'; +export { PrivilegeFormCalculator } from './src/privilege_form_calculator'; +export * as constants from './src/constants'; diff --git a/x-pack/packages/security/ui_components/jest.config.js b/x-pack/packages/security/ui_components/jest.config.js new file mode 100644 index 0000000000000..12c8dfc44691b --- /dev/null +++ b/x-pack/packages/security/ui_components/jest.config.js @@ -0,0 +1,15 @@ +/* + * 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. + */ + +module.exports = { + coverageDirectory: '/target/kibana-coverage/jest/x-pack/packages/security/ui_components', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/x-pack/packages/security/ui_components/**/*.{ts,tsx}'], + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/security/ui_components'], +}; diff --git a/x-pack/packages/security/ui_components/kibana.jsonc b/x-pack/packages/security/ui_components/kibana.jsonc new file mode 100644 index 0000000000000..1aad2d80ed7f7 --- /dev/null +++ b/x-pack/packages/security/ui_components/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/security-ui-components", + "owner": "@elastic/kibana-security" +} diff --git a/x-pack/packages/security/ui_components/package.json b/x-pack/packages/security/ui_components/package.json new file mode 100644 index 0000000000000..59bf7383b958e --- /dev/null +++ b/x-pack/packages/security/ui_components/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/security-ui-components", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts b/x-pack/packages/security/ui_components/src/constants.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts rename to x-pack/packages/security/ui_components/src/constants.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__fixtures__/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/__fixtures__/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__fixtures__/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/__fixtures__/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.test.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.test.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx index 5a43e7931d474..83a0da2e26815 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx @@ -18,7 +18,7 @@ import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { getDisplayedFeaturePrivileges } from './__fixtures__'; import { FeatureTable } from './feature_table'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; import { PrivilegeFormCalculator } from '../privilege_form_calculator'; const createRole = (kibana: Role['kibana'] = []): Role => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx index 6b4e7af240eb5..4b0d520dee661 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx @@ -35,7 +35,7 @@ import type { KibanaPrivileges, SecuredFeature } from '@kbn/security-role-manage import { ChangeAllPrivilegesControl } from './change_all_privileges'; import { FeatureTableExpandedRow } from './feature_table_expanded_row'; import { NO_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTableCell } from '../feature_table_cell'; +import { FeatureTableCell } from './components/feature_table_cell'; import type { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx index 92a33136c7678..3b787f01cdf92 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx @@ -15,7 +15,7 @@ import { import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { FeatureTableExpandedRow } from './feature_table_expanded_row'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; import { PrivilegeFormCalculator } from '../privilege_form_calculator'; const createRole = (kibana: Role['kibana'] = []): Role => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts similarity index 86% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts index 75d8daef05a3e..ad439d6aad3fa 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts @@ -6,3 +6,4 @@ */ export { FeatureTable } from './feature_table'; +export { FeatureTableCell } from './components'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.test.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.test.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/index.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/index.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts index b47501e08f376..0281605f00f34 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts +++ b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts @@ -11,7 +11,7 @@ import { } from '@kbn/security-role-management-model/src/__fixtures__'; import { PrivilegeFormCalculator } from './privilege_form_calculator'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; const createRole = (kibana: Role['kibana'] = []): Role => { return { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts diff --git a/x-pack/packages/security/ui_components/tsconfig.json b/x-pack/packages/security/ui_components/tsconfig.json new file mode 100644 index 0000000000000..736612a488852 --- /dev/null +++ b/x-pack/packages/security/ui_components/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node", "react"] + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["target/**/*"], + "kbn_references": [ + "@kbn/core", + "@kbn/i18n", + "@kbn/i18n-react", + "@kbn/security-plugin-types-common", + "@kbn/test-jest-helpers", + "@kbn/security-role-management-model", + "@kbn/features-plugin", + ] +} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index b724acc58f507..e867bf0c418cc 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -775,7 +775,9 @@ export const EditRolePage: FunctionComponent = ({ - Manage Members + {i18n.translate('xpack.security.management.roles.manageRoleUsers', { + defaultMessage: 'Manage Members', + })} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts index 6d9cb86ace188..01f924aaa555e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts @@ -8,10 +8,10 @@ import { EuiTableRow } from '@elastic/eui'; import type { ReactWrapper } from 'enzyme'; +import { FeatureTableCell } from '@kbn/security-ui-components'; import { findTestSubject } from '@kbn/test-jest-helpers'; import type { Role, RoleKibanaPrivilege } from '../../../../../../../../common'; -import { FeatureTableCell } from '../../feature_table_cell'; import { PrivilegeSummaryExpandedRow } from '../privilege_summary_expanded_row'; interface DisplayedFeaturePrivileges { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx index af15cf82b9be6..5dc856e5af5d9 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx @@ -27,6 +27,7 @@ import { type PrimaryFeaturePrivilege, type SecuredFeature, } from '@kbn/security-role-management-model'; +import { FeatureTableCell } from '@kbn/security-ui-components'; import type { Space, SpacesApiUi } from '@kbn/spaces-plugin/public'; import type { EffectiveFeaturePrivileges } from './privilege_summary_calculator'; @@ -34,7 +35,6 @@ import { PrivilegeSummaryCalculator } from './privilege_summary_calculator'; import { PrivilegeSummaryExpandedRow } from './privilege_summary_expanded_row'; import { SpaceColumnHeader } from './space_column_header'; import { ALL_SPACES_ID } from '../../../../../../../common/constants'; -import { FeatureTableCell } from '../feature_table_cell'; export interface PrivilegeSummaryTableProps { role: Role; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx index 72061958ecc35..403a9026923f2 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx @@ -9,7 +9,7 @@ import { EuiSelect } from '@elastic/eui'; import type { ChangeEvent } from 'react'; import React, { Component } from 'react'; -import { NO_PRIVILEGE_VALUE } from '../constants'; +import { constants } from '@kbn/security-ui-components'; interface Props { ['data-test-subj']: string; @@ -27,10 +27,10 @@ export class PrivilegeSelector extends Component { public render() { const { availablePrivileges, value, disabled, allowNone, compressed } = this.props; - const options = []; + const options: Array<{ value: string; text: string }> = []; if (allowNone) { - options.push({ value: NO_PRIVILEGE_VALUE, text: 'none' }); + options.push({ value: constants.NO_PRIVILEGE_VALUE, text: 'none' }); } options.push( diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx index b5b57921705e5..ad6415a1f4fec 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx @@ -16,17 +16,19 @@ import { import React, { Component, Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { Role, RoleKibanaPrivilege } from '@kbn/security-plugin-types-common'; import { isGlobalPrivilegeDefinition, type KibanaPrivileges, } from '@kbn/security-role-management-model'; +import { + constants, + KibanaPrivilegeTable, + PrivilegeFormCalculator, +} from '@kbn/security-ui-components'; import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning'; -import type { Role, RoleKibanaPrivilege } from '../../../../../../../common'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTable } from '../feature_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { role: Role; @@ -98,7 +100,7 @@ export class SimplePrivilegeSection extends Component { onChange={this.onKibanaPrivilegeChange} options={[ { - value: NO_PRIVILEGE_VALUE, + value: constants.NO_PRIVILEGE_VALUE, inputDisplay: ( { ), }, { - value: CUSTOM_PRIVILEGE_VALUE, + value: constants.CUSTOM_PRIVILEGE_VALUE, inputDisplay: ( { {this.state.isCustomizingGlobalPrivilege && ( - { public getDisplayedBasePrivilege = () => { if (this.state.isCustomizingGlobalPrivilege) { - return CUSTOM_PRIVILEGE_VALUE; + return constants.CUSTOM_PRIVILEGE_VALUE; } const { role } = this.props; const form = this.locateGlobalPrivilege(role); - return form && form.base.length > 0 ? form.base[0] : NO_PRIVILEGE_VALUE; + return form && form.base.length > 0 ? form.base[0] : constants.NO_PRIVILEGE_VALUE; }; public onKibanaPrivilegeChange = (privilege: string) => { @@ -254,10 +256,10 @@ export class SimplePrivilegeSection extends Component { const form = this.locateGlobalPrivilege(role) || this.createGlobalPrivilegeEntry(role); - if (privilege === NO_PRIVILEGE_VALUE) { + if (privilege === constants.NO_PRIVILEGE_VALUE) { // Remove global entry if no privilege value role.kibana = role.kibana.filter((entry) => !isGlobalPrivilegeDefinition(entry)); - } else if (privilege === CUSTOM_PRIVILEGE_VALUE) { + } else if (privilege === constants.CUSTOM_PRIVILEGE_VALUE) { // Remove base privilege if customizing feature privileges form.base = []; } else { @@ -267,7 +269,7 @@ export class SimplePrivilegeSection extends Component { this.props.onChange(role); this.setState({ - isCustomizingGlobalPrivilege: privilege === CUSTOM_PRIVILEGE_VALUE, + isCustomizingGlobalPrivilege: privilege === constants.CUSTOM_PRIVILEGE_VALUE, globalPrivsIndex: role.kibana.indexOf(form), }); }; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx index 52e61c6e92603..40d0da4fbb0c2 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx @@ -11,7 +11,7 @@ import _ from 'lodash'; import type { FC, ReactNode } from 'react'; import React from 'react'; -import { NO_PRIVILEGE_VALUE } from '../constants'; +import { constants } from '@kbn/security-ui-components'; interface Props extends PropsOf { privilege: string | string[] | undefined; @@ -40,7 +40,8 @@ function getDisplayValue(privilege: string | string[] | undefined) { let displayValue: string | ReactNode; const isPrivilegeMissing = - privileges.length === 0 || (privileges.length === 1 && privileges.includes(NO_PRIVILEGE_VALUE)); + privileges.length === 0 || + (privileges.length === 1 && privileges.includes(constants.NO_PRIVILEGE_VALUE)); if (isPrivilegeMissing) { displayValue = ; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx index 7d9d6d015c03e..406e102b4529d 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx @@ -13,14 +13,14 @@ import { createKibanaPrivileges, kibanaFeatures, } from '@kbn/security-role-management-model/src/__fixtures__'; +import { KibanaPrivilegeTable as FeatureTable } from '@kbn/security-ui-components'; +import { getDisplayedFeaturePrivileges } from '@kbn/security-ui-components/src/kibana_privilege_table/__fixtures__'; import type { Space } from '@kbn/spaces-plugin/public'; import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { SpaceSelector } from './space_selector'; import type { Role } from '../../../../../../../common'; -import { FeatureTable } from '../feature_table'; -import { getDisplayedFeaturePrivileges } from '../feature_table/__fixtures__'; const createRole = (kibana: Role['kibana'] = []): Role => { return { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx index fbcc43a3b4b1a..a37fd799a035e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx @@ -30,15 +30,17 @@ import React, { Component, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { KibanaPrivileges } from '@kbn/security-role-management-model'; +import { + KibanaPrivilegeTable, + PrivilegeFormCalculator, + constants as UI_CONSTANTS, +} from '@kbn/security-ui-components'; import type { Space } from '@kbn/spaces-plugin/public'; import { SpaceSelector } from './space_selector'; import type { FeaturesPrivileges, Role } from '../../../../../../../common'; import { ALL_SPACES_ID } from '../../../../../../../common/constants'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTable } from '../feature_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { role: Role; @@ -254,7 +256,7 @@ export class PrivilegeSpaceForm extends Component { - { let isCustomizingFeaturePrivileges = false; - if (privilegeName === CUSTOM_PRIVILEGE_VALUE) { + if (privilegeName === UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE) { form.base = []; isCustomizingFeaturePrivileges = true; } else { @@ -456,7 +458,8 @@ export class PrivilegeSpaceForm extends Component { } this.setState({ - selectedBasePrivilege: privilegeName === CUSTOM_PRIVILEGE_VALUE ? [] : [privilegeName], + selectedBasePrivilege: + privilegeName === UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE ? [] : [privilegeName], role, isCustomizingFeaturePrivileges, privilegeCalculator: new PrivilegeFormCalculator(this.props.kibanaPrivileges, role), @@ -507,7 +510,7 @@ export class PrivilegeSpaceForm extends Component { return `basePrivilege_${basePrivilege.id}`; } - return `basePrivilege_${CUSTOM_PRIVILEGE_VALUE}`; + return `basePrivilege_${UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE}`; }; private onFeaturePrivilegesChange = (featureId: string, privileges: string[]) => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx index 316419f479426..e0478394852bc 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx @@ -12,11 +12,11 @@ import React from 'react'; import { KibanaFeature } from '@kbn/features-plugin/public'; import type { Role, RoleKibanaPrivilege } from '@kbn/security-plugin-types-common'; import { createKibanaPrivileges } from '@kbn/security-role-management-model/src/__fixtures__'; +import { PrivilegeFormCalculator } from '@kbn/security-ui-components'; import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { PrivilegeDisplay } from './privilege_display'; import { PrivilegeSpaceTable } from './privilege_space_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface TableRow { spaces: string[]; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx index 28e1d50d7f71e..61a31f5575800 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx @@ -24,13 +24,12 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { FeaturesPrivileges, Role } from '@kbn/security-plugin-types-common'; import { isGlobalPrivilegeDefinition } from '@kbn/security-role-management-model'; +import { constants, type PrivilegeFormCalculator } from '@kbn/security-ui-components'; import type { Space } from '@kbn/spaces-plugin/public'; import { getSpaceColor } from '@kbn/spaces-plugin/public'; import { PrivilegeDisplay } from './privilege_display'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE } from '../constants'; -import type { PrivilegeFormCalculator } from '../privilege_form_calculator'; const SPACES_DISPLAY_COUNT = 4; @@ -120,7 +119,7 @@ export class PrivilegeSpaceTable extends Component { const isExpanded = this.state.expandedSpacesGroups.includes(record.privilegeIndex); const displayedSpaces = isExpanded ? spaces : spaces.slice(0, SPACES_DISPLAY_COUNT); - let button = null; + let button: React.ReactElement | null = null; if (spaces.length > displayedSpaces.length) { button = ( { const basePrivilege = privilegeCalculator.getBasePrivilege(record.privilegeIndex)?.id ?? - CUSTOM_PRIVILEGE_VALUE; + constants.CUSTOM_PRIVILEGE_VALUE; const privilege = privilegeCalculator.isWildcardBasePrivilege(record.privilegeIndex) ? '*' diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx index 404bd39ec9b67..e5a4cb1494d77 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx @@ -22,13 +22,13 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { Role } from '@kbn/security-plugin-types-common'; import type { KibanaPrivileges } from '@kbn/security-role-management-model'; +import { PrivilegeFormCalculator } from '@kbn/security-ui-components'; import type { Space, SpacesApiUi } from '@kbn/spaces-plugin/public'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { PrivilegeSpaceTable } from './privilege_space_table'; import { isRoleReserved, isRoleWithWildcardBasePrivilege } from '../../../../../../../common'; import type { RoleValidator } from '../../../validate_role'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; import { PrivilegeSummary } from '../privilege_summary'; interface Props { diff --git a/x-pack/plugins/security/tsconfig.json b/x-pack/plugins/security/tsconfig.json index 8e3f38833248d..c3df5dda29481 100644 --- a/x-pack/plugins/security/tsconfig.json +++ b/x-pack/plugins/security/tsconfig.json @@ -86,6 +86,7 @@ "@kbn/core-security-server-mocks", "@kbn/security-authorization-core", "@kbn/security-role-management-model", + "@kbn/security-ui-components", ], "exclude": [ "target/**/*", diff --git a/yarn.lock b/yarn.lock index 15ae0b8e5fcee..4ee86f1601adb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6339,6 +6339,10 @@ version "0.0.0" uid "" +"@kbn/security-ui-components@link:x-pack/packages/security/ui_components": + version "0.0.0" + uid "" + "@kbn/securitysolution-autocomplete@link:packages/kbn-securitysolution-autocomplete": version "0.0.0" uid "" From 51e76d8ad67ff7c75875e834999b40422c578bc0 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Tue, 27 Aug 2024 07:18:04 -0700 Subject: [PATCH 35/38] Onboard Synthetics TLS rule type with FAAD (#191127) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: https://github.com/elastic/kibana/issues/169867 This is the second attempt PR 🙂 to onboard the Synthetics TLS rule type with FAAD. **To verify** 1. Create an oblt cluster with `/create-ccs-cluster` on slack. Choose `dev-oblt`. 2. Add the configuration values from the oblt command to your kibana.yml. You may have to add: ``` elasticsearch.ignoreVersionMismatch: true ``` and start Kibana 4. Navigate to `app/synthetics/settings/alerting` and add a default connector. 5. Go to `/app/synthetics/monitors/getting-started` and create a HTTP Ping monitor with whatever url you want ( I used https://github.com/) and select a location. 6. Go back to `app/synthetics` and click the Alerts & Rules link. Click TLS certificate rule. Edit the older than param to something low, such as 1 day. 7. The TLS rule should create an active alert, verify that the action message is populated. 8. Repeat step 5 update the older than param to be higher than the age of the cert. You can check your cert here `app/synthetics/certificates` 9. The TLS rule should recover, and verify that the recovery action message is populated. 10. You can also check the AAD docs in dev tools using the following command: ``` GET .internal.alerts-observability.uptime.alerts*/_search ``` --- .../synthetics/server/alert_rules/common.ts | 3 +- .../status_rule/monitor_status_rule.ts | 14 +- .../tls_rule/message_utils.test.ts | 167 ++++++++++++++++++ .../alert_rules/tls_rule/message_utils.ts | 41 +++-- .../server/alert_rules/tls_rule/tls_rule.ts | 106 ++++++----- .../synthetics/server/server.ts | 14 +- 6 files changed, 259 insertions(+), 86 deletions(-) create mode 100644 x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts index 549bbcff4cdfe..20c84109b0be1 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts @@ -359,8 +359,9 @@ export const syntheticsRuleTypeFieldMap = { ...legacyExperimentalFieldMap, }; -export const SyntheticsRuleTypeAlertDefinition: IRuleTypeAlerts = { +export const SyntheticsRuleTypeAlertDefinition: IRuleTypeAlerts = { context: SYNTHETICS_RULE_TYPES_ALERT_CONTEXT, mappings: { fieldMap: syntheticsRuleTypeFieldMap }, useLegacyAlerts: true, + shouldWrite: true, }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts index d042e8d323302..c823abe7d083f 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts @@ -8,13 +8,11 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { isEmpty } from 'lodash'; import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; -import { PluginSetupContract } from '@kbn/alerting-plugin/server'; import { GetViewInAppRelativeUrlFnOpts, AlertInstanceContext as AlertContext, RuleExecutorOptions, AlertsClientError, - IRuleTypeAlerts, } from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; @@ -55,16 +53,15 @@ type MonitorStatusAlert = ObservabilityUptimeAlert; export const registerSyntheticsStatusCheckRule = ( server: SyntheticsServerSetup, plugins: SyntheticsPluginsSetupDependencies, - syntheticsMonitorClient: SyntheticsMonitorClient, - alerting: PluginSetupContract + syntheticsMonitorClient: SyntheticsMonitorClient ) => { - if (!alerting) { + if (!plugins.alerting) { throw new Error( 'Cannot register the synthetics monitor status rule type. The alerting plugin needs to be enabled.' ); } - alerting.registerType({ + plugins.alerting.registerType({ id: SYNTHETICS_ALERT_RULE_TYPES.MONITOR_STATUS, category: DEFAULT_APP_CATEGORIES.observability.id, producer: 'uptime', @@ -172,10 +169,7 @@ export const registerSyntheticsStatusCheckRule = ( state: updateState(ruleState, !isEmpty(downConfigs), { downConfigs }), }; }, - alerts: { - ...SyntheticsRuleTypeAlertDefinition, - shouldWrite: true, - } as IRuleTypeAlerts, + alerts: SyntheticsRuleTypeAlertDefinition, fieldsForAAD: Object.keys(syntheticsRuleFieldMap), getViewInAppRelativeUrl: ({ rule }: GetViewInAppRelativeUrlFnOpts<{}>) => observabilityPaths.ruleDetails(rule.id), diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts new file mode 100644 index 0000000000000..e07ba00c1de6c --- /dev/null +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts @@ -0,0 +1,167 @@ +/* + * 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 { IBasePath } from '@kbn/core/server'; +import { AlertsLocatorParams } from '@kbn/observability-plugin/common'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { setTLSRecoveredAlertsContext } from './message_utils'; +import { TLSLatestPing } from './tls_rule_executor'; + +describe('setTLSRecoveredAlertsContext', () => { + const timestamp = new Date().toISOString(); + const alertUuid = 'alert-id'; + const configId = '12345'; + const basePath = { + publicBaseUrl: 'https://localhost:5601', + } as IBasePath; + const alertsLocatorMock = { + getLocation: jest.fn().mockImplementation(() => ({ + path: 'https://localhost:5601/app/observability/alerts/alert-id', + })), + } as any as LocatorPublic; + const alertState = { + summary: 'test-summary', + status: 'has expired', + sha256: 'cert-1-sha256', + commonName: 'cert-1', + issuer: 'test-issuer', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + locationName: 'test-location-name', + monitorUrl: 'test-monitor-url', + configId, + }; + + it('sets context correctly when monitor cert has been updated', async () => { + const alertsClientMock = { + report: jest.fn(), + getAlertLimitValue: jest.fn().mockReturnValue(10), + setAlertLimitReached: jest.fn(), + getRecoveredAlerts: jest.fn().mockReturnValue([ + { + alert: { + getId: () => alertUuid, + getState: () => alertState, + setContext: jest.fn(), + getUuid: () => alertUuid, + getStart: () => new Date().toISOString(), + }, + }, + ]), + setAlertData: jest.fn(), + isTrackedAlert: jest.fn(), + }; + await setTLSRecoveredAlertsContext({ + alertsClient: alertsClientMock, + basePath, + defaultStartedAt: timestamp, + spaceId: 'default', + alertsLocator: alertsLocatorMock, + latestPings: [ + { + config_id: configId, + '@timestamp': timestamp, + tls: { + server: { + hash: { + sha256: 'cert-2-sha256', + }, + x509: { + subject: { + common_name: 'cert-2', + }, + not_after: timestamp, + }, + }, + }, + } as TLSLatestPing, + ], + }); + expect(alertsClientMock.setAlertData).toBeCalledWith({ + context: { + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + commonName: 'cert-1', + configId: '12345', + issuer: 'test-issuer', + locationName: 'test-location-name', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + monitorUrl: 'test-monitor-url', + newStatus: expect.stringContaining('Certificate cert-2 Expired on'), + previousStatus: 'Certificate cert-1 test-summary', + sha256: 'cert-1-sha256', + status: 'has expired', + summary: 'Monitor certificate has been updated.', + }, + id: 'alert-id', + }); + }); + + it('sets context correctly when monitor cert expiry/age threshold has been updated', async () => { + const alertsClientMock = { + report: jest.fn(), + getAlertLimitValue: jest.fn().mockReturnValue(10), + setAlertLimitReached: jest.fn(), + getRecoveredAlerts: jest.fn().mockReturnValue([ + { + alert: { + getId: () => alertUuid, + getState: () => alertState, + setContext: jest.fn(), + getUuid: () => alertUuid, + getStart: () => new Date().toISOString(), + }, + }, + ]), + setAlertData: jest.fn(), + isTrackedAlert: jest.fn(), + }; + await setTLSRecoveredAlertsContext({ + alertsClient: alertsClientMock, + basePath, + defaultStartedAt: timestamp, + spaceId: 'default', + alertsLocator: alertsLocatorMock, + latestPings: [ + { + config_id: configId, + '@timestamp': timestamp, + tls: { + server: { + hash: { + sha256: 'cert-1-sha256', + }, + x509: { + subject: { + common_name: 'cert-1', + }, + not_after: timestamp, + }, + }, + }, + } as TLSLatestPing, + ], + }); + expect(alertsClientMock.setAlertData).toBeCalledWith({ + context: { + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + commonName: 'cert-1', + configId: '12345', + issuer: 'test-issuer', + locationName: 'test-location-name', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + monitorUrl: 'test-monitor-url', + newStatus: 'Certificate cert-1 test-summary', + previousStatus: 'Certificate cert-1 test-summary', + sha256: 'cert-1-sha256', + status: 'has expired', + summary: 'Expiry/Age threshold has been updated.', + }, + id: 'alert-id', + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts index 78e073d9233a9..5fc23a370caea 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts @@ -9,12 +9,19 @@ import moment from 'moment/moment'; import { IBasePath } from '@kbn/core-http-server'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { AlertsLocatorParams, getAlertUrl } from '@kbn/observability-plugin/common'; -import { RuleExecutorServices } from '@kbn/alerting-plugin/server'; +import { + AlertInstanceContext as AlertContext, + AlertInstanceState as AlertState, + ActionGroupIdsOf, +} from '@kbn/alerting-plugin/server'; import { i18n } from '@kbn/i18n'; +import { PublicAlertsClient } from '@kbn/alerting-plugin/server/alerts_client/types'; +import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; import { TLSLatestPing } from './tls_rule_executor'; import { ALERT_DETAILS_URL } from '../action_variables'; import { Cert } from '../../../common/runtime_types'; import { tlsTranslations } from '../translations'; +import { MonitorStatusActionGroup } from '../../../common/constants/synthetics_alerts'; interface TLSContent { summary: string; status?: string; @@ -75,35 +82,34 @@ export const getCertSummary = (cert: Cert, expirationThreshold: number, ageThres }; }; -type CertSummary = ReturnType; - export const setTLSRecoveredAlertsContext = async ({ - alertFactory, + alertsClient, basePath, defaultStartedAt, - getAlertStartedDate, spaceId, alertsLocator, - getAlertUuid, latestPings, }: { - alertFactory: RuleExecutorServices['alertFactory']; + alertsClient: PublicAlertsClient< + ObservabilityUptimeAlert, + AlertState, + AlertContext, + ActionGroupIdsOf + >; defaultStartedAt: string; - getAlertStartedDate: (alertInstanceId: string) => string | null; basePath: IBasePath; spaceId: string; alertsLocator?: LocatorPublic; - getAlertUuid?: (alertId: string) => string | null; latestPings: TLSLatestPing[]; }) => { - const { getRecoveredAlerts } = alertFactory.done(); + const recoveredAlerts = alertsClient.getRecoveredAlerts() ?? []; - for await (const alert of getRecoveredAlerts()) { - const recoveredAlertId = alert.getId(); - const alertUuid = getAlertUuid?.(recoveredAlertId) || null; - const indexedStartedAt = getAlertStartedDate(recoveredAlertId) ?? defaultStartedAt; + for (const recoveredAlert of recoveredAlerts) { + const recoveredAlertId = recoveredAlert.alert.getId(); + const alertUuid = recoveredAlert.alert.getUuid(); + const indexedStartedAt = recoveredAlert.alert.getStart() ?? defaultStartedAt; - const state = alert.getState() as CertSummary; + const state = recoveredAlert.alert.getState(); const alertUrl = await getAlertUrl( alertUuid, spaceId, @@ -144,12 +150,13 @@ export const setTLSRecoveredAlertsContext = async ({ newStatus = previousStatus; } - alert.setContext({ + const context = { ...state, newStatus, previousStatus, summary: newSummary, [ALERT_DETAILS_URL]: alertUrl, - }); + }; + alertsClient.setAlertData({ id: recoveredAlertId, context }); } }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts index b251e950a5d4a..3aaafcaf17468 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts @@ -7,8 +7,12 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; -import { GetViewInAppRelativeUrlFnOpts } from '@kbn/alerting-plugin/server'; -import { createLifecycleRuleTypeFactory, IRuleDataClient } from '@kbn/rule-registry-plugin/server'; +import { + GetViewInAppRelativeUrlFnOpts, + AlertInstanceContext as AlertContext, + RuleExecutorOptions, + AlertsClientError, +} from '@kbn/alerting-plugin/server'; import { asyncForEach } from '@kbn/std'; import { ALERT_REASON, ALERT_UUID } from '@kbn/rule-data-utils'; import { @@ -19,6 +23,7 @@ import { } from '@kbn/observability-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { schema } from '@kbn/config-schema'; +import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; import { syntheticsRuleFieldMap } from '../../../common/rules/synthetics_rule_field_map'; import { SyntheticsPluginsSetupDependencies, SyntheticsServerSetup } from '../../types'; import { TlsTranslations } from '../../../common/rules/synthetics/translations'; @@ -39,21 +44,27 @@ import { import { generateAlertMessage, SyntheticsRuleTypeAlertDefinition, updateState } from '../common'; import { ALERT_DETAILS_URL, getActionVariables } from '../action_variables'; import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client'; +import { TLSParams } from '../../../common/runtime_types/alerts/tls'; -export type ActionGroupIds = ActionGroupIdsOf; +type TLSRuleTypeParams = TLSParams; +type TLSActionGroups = ActionGroupIdsOf; +type TLSRuleTypeState = SyntheticsCommonState; +type TLSAlertState = ReturnType; +type TLSAlertContext = AlertContext; +type TLSAlert = ObservabilityUptimeAlert; export const registerSyntheticsTLSCheckRule = ( server: SyntheticsServerSetup, plugins: SyntheticsPluginsSetupDependencies, - syntheticsMonitorClient: SyntheticsMonitorClient, - ruleDataClient: IRuleDataClient + syntheticsMonitorClient: SyntheticsMonitorClient ) => { - const createLifecycleRuleType = createLifecycleRuleTypeFactory({ - ruleDataClient, - logger: server.logger, - }); + if (!plugins.alerting) { + throw new Error( + 'Cannot register the synthetics TLS check rule type. The alerting plugin needs to be enabled.' + ); + } - return createLifecycleRuleType({ + plugins.alerting.registerType({ id: SYNTHETICS_ALERT_RULE_TYPES.TLS, category: DEFAULT_APP_CATEGORIES.observability.id, producer: 'uptime', @@ -71,22 +82,25 @@ export const registerSyntheticsTLSCheckRule = ( isExportable: true, minimumLicenseRequired: 'basic', doesSetRecoveryContext: true, - async executor({ state, params, services, spaceId, previousStartedAt, startedAt }) { - const ruleState = state as SyntheticsCommonState; - + executor: async ( + options: RuleExecutorOptions< + TLSRuleTypeParams, + TLSRuleTypeState, + TLSAlertState, + TLSAlertContext, + TLSActionGroups, + TLSAlert + > + ) => { + const { state: ruleState, params, services, spaceId, previousStartedAt, startedAt } = options; + const { alertsClient, savedObjectsClient, scopedClusterClient } = services; + if (!alertsClient) { + throw new AlertsClientError(); + } const { basePath, share } = server; const alertsLocator: LocatorPublic | undefined = share.url.locators.get(alertsLocatorID); - const { - alertFactory, - getAlertUuid, - savedObjectsClient, - scopedClusterClient, - alertWithLifecycle, - getAlertStartedDate, - } = services; - const tlsRule = new TLSRuleExecutor( previousStartedAt, params, @@ -107,45 +121,45 @@ export const registerSyntheticsTLSCheckRule = ( } const alertId = cert.sha256; - const alertUuid = getAlertUuid(alertId); - const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString(); - - const alertInstance = alertWithLifecycle({ + const { uuid, start } = alertsClient.report({ id: alertId, - fields: { - [CERT_COMMON_NAME]: cert.common_name, - [CERT_ISSUER_NAME]: cert.issuer, - [CERT_VALID_NOT_AFTER]: cert.not_after, - [CERT_VALID_NOT_BEFORE]: cert.not_before, - [CERT_HASH_SHA256]: cert.sha256, - [ALERT_UUID]: alertUuid, - [ALERT_REASON]: generateAlertMessage(TlsTranslations.defaultActionMessage, summary), - }, + actionGroup: TLS_CERTIFICATE.id, + state: { ...updateState(ruleState, foundCerts), ...summary }, }); - - alertInstance.replaceState({ - ...updateState(ruleState, foundCerts), - ...summary, - }); - - alertInstance.scheduleActions(TLS_CERTIFICATE.id, { + const indexedStartedAt = start ?? startedAt.toISOString(); + + const payload = { + [CERT_COMMON_NAME]: cert.common_name, + [CERT_ISSUER_NAME]: cert.issuer, + [CERT_VALID_NOT_AFTER]: cert.not_after, + [CERT_VALID_NOT_BEFORE]: cert.not_before, + [CERT_HASH_SHA256]: cert.sha256, + [ALERT_UUID]: uuid, + [ALERT_REASON]: generateAlertMessage(TlsTranslations.defaultActionMessage, summary), + }; + + const context = { [ALERT_DETAILS_URL]: await getAlertUrl( - alertUuid, + uuid, spaceId, indexedStartedAt, alertsLocator, basePath.publicBaseUrl ), ...summary, + }; + + alertsClient.setAlertData({ + id: alertId, + payload, + context, }); }); await setTLSRecoveredAlertsContext({ - alertFactory, + alertsClient, basePath, defaultStartedAt: startedAt.toISOString(), - getAlertStartedDate, - getAlertUuid, spaceId, alertsLocator, latestPings, diff --git a/x-pack/plugins/observability_solution/synthetics/server/server.ts b/x-pack/plugins/observability_solution/synthetics/server/server.ts index b394e4ffc6883..77937c57590e7 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/server.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/server.ts @@ -138,16 +138,6 @@ export const initSyntheticsServer = ( } }); - const { alerting } = plugins; - - registerSyntheticsStatusCheckRule(server, plugins, syntheticsMonitorClient, alerting); - - const tlsRule = registerSyntheticsTLSCheckRule( - server, - plugins, - syntheticsMonitorClient, - ruleDataClient - ); - - alerting.registerType(tlsRule); + registerSyntheticsStatusCheckRule(server, plugins, syntheticsMonitorClient); + registerSyntheticsTLSCheckRule(server, plugins, syntheticsMonitorClient); }; From 8e9b82718151c0ae4754d1e25727e8c698b35a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20=C3=81brah=C3=A1m?= Date: Tue, 27 Aug 2024 16:50:39 +0200 Subject: [PATCH 36/38] [Defend Workflows] Fix artifact entries list FTR (#189961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary **tl;wr;** - instead of selecting from dropdown, values are entered for Event Filters - artifacts for update/delete test cases are created via API call instead of UI interaction > [!note] > FTRs needs to be re-enabled before merge, revert this e0858a516caa6fe6a41b4782c25deafe96c06ca6 - done ✅ --- This PR attempts to decrease flakiness in `artifact_entries_list` FTR. Looks like the reason for flakiness was the dropdown for the field to be filtered. After spending a bit of a time looking at the code, couldn't find any quick solution why it can be flaky, so instead just tried to improve the tests. For that, added a 'special' (aka hack) test case to just try to set event filter 100 times, and also a failing test case just to receive logs (77455d73e8743fd543e54271e56ab9b408d012ba) - that's why all flaky runners are red, you need to see the logs. It didn't work to add some waits to let React re-render and let the API call for suggestions be finished, didn't work to select from dropdown by text instead of test id, didn't work to add even more wait in between multiple user actions. See logs here and search for `results are in` inside the logs: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6744#019145e0-445d-4978-89c8-701908e14e3f image In the end, looks like the solution is simply `input` the values instead of selecting them from the dropdown. In the last hacky-flaky run, it passed all 100 times: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6756 image And a last flaky run without the hack, with the official flaky runner: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6772 100/100 ✅ Also, entries for the update/delete test cases are created via API call instead of UI interaction, so those cases overlap less with the create test case. --------- Co-authored-by: Elastic Machine --- .../integrations/artifact_entries_list.ts | 23 +++--- .../apps/integrations/mocks.ts | 76 +++++++++++++++++-- .../services/endpoint_artifacts.ts | 27 ++++++- 3 files changed, 106 insertions(+), 20 deletions(-) diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts index 9cb093b6edae8..1f5d406617ae2 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts @@ -35,7 +35,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const retry = getService('retry'); const esClient = getService('es'); const supertest = getService('supertest'); - const find = getService('find'); const toasts = getService('toasts'); const policyTestResources = getService('policyTestResources'); const unzipPromisify = promisify(unzip); @@ -52,12 +51,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true'); }; - // Failing: See https://github.com/elastic/kibana/issues/187314 - // Failing: See https://github.com/elastic/kibana/issues/187383 - // Failing: See https://github.com/elastic/kibana/issues/188131 - // Failing: See https://github.com/elastic/kibana/issues/188125 - describe.skip('For each artifact list under management', function () { - targetTags(this, ['@ess', '@skipInServerless']); + describe('For each artifact list under management', function () { + targetTags(this, ['@ess', '@serverless']); this.timeout(60_000 * 5); let indexedData: IndexedHostsAndAlertsResponse; @@ -154,9 +149,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { suffix?: string ) => { for (const formAction of actions) { - if (formAction.type === 'customClick') { - await find.clickByCssSelector(formAction.selector, testSubjects.FIND_TIME); - } else if (formAction.type === 'click') { + if (formAction.type === 'click') { await testSubjects.click(formAction.selector); } else if (formAction.type === 'input') { const newValue = (formAction.value || '') + (suffix ? suffix : ''); @@ -265,7 +258,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it(`should be able to update an existing ${testData.title} entry`, async () => { - await createArtifact(testData); + await endpointArtifactsTestResources.createArtifact(testData.listId, testData.createBody); + await browser.refresh(); + await updateArtifact(testData, { policyId: policyInfo.packagePolicy.id }); // Check edited artifact is in the list with new values (wait for list to be updated) @@ -299,7 +294,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it(`should be able to delete the existing ${testData.title} entry`, async () => { - await createArtifact(testData); + await endpointArtifactsTestResources.createArtifact(testData.listId, testData.createBody); + await browser.refresh(); + await deleteArtifact(testData); // We only expect one artifact to have been visible await testSubjects.missingOrFail(testData.delete.card); @@ -336,7 +333,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); const testData = getCreateMultipleData(); - it(`should get correct atifact when multiple entries are created`, async () => { + it(`should get correct artifact when multiple entries are created`, async () => { // Create first trusted app await createArtifact(testData, { policyId: firstPolicy.packagePolicy.id, diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts b/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts index 47523694b4349..de88f99048c6c 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts @@ -7,8 +7,11 @@ import { FullAgentPolicy } from '@kbn/fleet-plugin/common/types'; import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services/artifacts/types'; +import { GLOBAL_ARTIFACT_TAG } from '@kbn/security-solution-plugin/common/endpoint/service/artifacts'; import { InternalUnifiedManifestBaseSchema } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts'; import { TranslatedExceptionListItem } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts/lists'; +import { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; export interface AgentPolicyResponseType { _index: string; @@ -119,6 +122,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'trustedAppsListPage-deleteModal-submitButton', card: 'trustedAppsListPage-card', }, + listId: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, + createBody: { + entries: [ + { + type: 'match', + field: 'process.hash.sha256', + value: 'a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'trusted_apps', pageObject: 'trustedApps', fleetArtifact: { @@ -206,8 +222,9 @@ export const getArtifactsListTestsData = () => [ selector: 'fieldAutocompleteComboBox', }, { - type: 'customClick', - selector: 'button[title="agent.ephemeral_id"]', + type: 'input', + selector: 'fieldAutocompleteComboBox', + value: 'agent.ephemeral_id', }, { type: 'click', @@ -247,10 +264,6 @@ export const getArtifactsListTestsData = () => [ selector: 'fieldAutocompleteComboBox', value: 'agent.id', }, - { - type: 'customClick', - selector: 'button[title="agent.id"]', - }, { type: 'input', selector: 'valuesAutocompleteMatch', @@ -281,6 +294,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'EventFiltersListPage-deleteModal-submitButton', card: 'EventFiltersListPage-card', }, + listId: ENDPOINT_ARTIFACT_LISTS.eventFilters.id, + createBody: { + entries: [ + { + field: 'agent.ephemeral_id', + value: 'endpoint', + type: 'match', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'event_filters', pageObject: 'eventFilters', fleetArtifact: { @@ -456,6 +482,31 @@ export const getArtifactsListTestsData = () => [ card: 'blocklistCard', }, pageObject: 'blocklist', + listId: ENDPOINT_ARTIFACT_LISTS.blocklists.id, + createBody: { + entries: [ + { + type: 'match_any', + field: 'file.hash.md5', + value: ['741462ab431a22233c787baab9b653c7'], + operator: 'included', + }, + { + type: 'match_any', + field: 'file.hash.sha1', + value: ['aedb279e378bed6c2db3c9dc9e12ba635e0b391c'], + operator: 'included', + }, + { + type: 'match_any', + field: 'file.hash.sha256', + value: ['a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476'], + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'blocklist', fleetArtifact: { identifier: 'endpoint-blocklist-windows-v1', @@ -610,6 +661,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'hostIsolationExceptionsDeletionConfirm', card: 'hostIsolationExceptionsCard', }, + listId: ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id, + createBody: { + entries: [ + { + type: 'match', + field: 'destination.ip', + value: '1.1.1.1', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows', 'linux', 'macos'], + } as Partial, pageObject: 'hostIsolationExceptions', urlPath: 'host_isolation_exceptions', fleetArtifact: { diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts index 6f24f543c89ef..ce0d5ce6cda41 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts @@ -10,7 +10,12 @@ import type { CreateExceptionListSchema, ExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; -import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; +import { + ENDPOINT_ARTIFACT_LISTS, + ENDPOINT_ARTIFACT_LIST_IDS, + EXCEPTION_LIST_ITEM_URL, + EXCEPTION_LIST_URL, +} from '@kbn/securitysolution-list-constants'; import { Response } from 'superagent'; import { ExceptionsListItemGenerator } from '@kbn/security-solution-plugin/common/endpoint/data_generators/exceptions_list_item_generator'; import { TRUSTED_APPS_EXCEPTION_LIST_DEFINITION } from '@kbn/security-solution-plugin/public/management/pages/trusted_apps/constants'; @@ -122,6 +127,26 @@ export class EndpointArtifactsTestResources extends FtrService { return this.createExceptionItem(blocklist); } + async createArtifact( + listId: (typeof ENDPOINT_ARTIFACT_LIST_IDS)[number], + overrides: Partial = {} + ): Promise { + switch (listId) { + case ENDPOINT_ARTIFACT_LISTS.trustedApps.id: { + return this.createTrustedApp(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.eventFilters.id: { + return this.createEventFilter(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.blocklists.id: { + return this.createBlocklist(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id: { + return this.createHostIsolationException(overrides); + } + } + } + async getArtifactsFromUnifiedManifestSO(): Promise< Array< InternalUnifiedManifestSchemaResponseType['_source']['endpoint:unified-user-artifact-manifest'] From 2441e9ac8f38a561c5572a08162d0822f24074d8 Mon Sep 17 00:00:00 2001 From: Yngrid Coello Date: Tue, 27 Aug 2024 17:28:53 +0200 Subject: [PATCH 37/38] [Dataset quality] Enable page for metrics and traces (#190043) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/elastic/observability-dev/issues/3454. This PR enables Dataset quality for being used for `traces` and `metrics`. ### Changes - Added `KNOWN_TYPES` array containing the types that we allow in dataset quality page. - `datasets`, `degradedDocs` and `nonAggregatableDatasets` are now wrapped in an state. This allow us to retrigger the calls whenever we need to do it (e.g. when changing timeframe), more importantly now whenever we select a new type of dataset. - The `invoke` `degradedDocs` is created dynamically depending on the types present in `KNOWN_TYPES`. - `GET /internal/dataset_quality/data_streams/stats` and `GET /internal/dataset_quality/data_streams/non_aggregatable` now accept an array of `DataStreamType`. This allow us to query the information for multiple types of dataStreams at the same time. - degradedDocs are stored now locally as a nested structure. This nested structure allow us to update just the needed portion instead of updating all datasets whenever a change occurs (e.g. a type is deselected). - redirectLink now takes into account the datastream type, it only redirects to logs explorer if it's enabled and the type of the datastream is logs. ### 🎥 Demo https://github.com/user-attachments/assets/082bd4e9-a8f8-4af9-a425-267adc3b30df --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../dataset_quality_url_schema_v1.ts | 1 + x-pack/plugins/data_quality/server/plugin.ts | 14 + .../dataset_quality/common/constants.ts | 6 +- .../common/data_stream_details/types.ts | 3 - .../common/data_streams_stats/types.ts | 3 - .../dataset_quality/filters/filters.tsx | 31 ++ .../dataset_quality/filters/selector.tsx | 102 ++++++ .../components/dataset_quality/header.tsx | 13 +- .../dataset_quality/table/columns.tsx | 13 + .../document_trends/degraded_docs/index.tsx | 6 +- .../hooks/use_dataset_quality_filters.ts | 28 +- .../hooks/use_dataset_quality_table.tsx | 11 +- .../hooks/use_dataset_quality_warnings.ts | 7 +- .../public/hooks/use_empty_state.ts | 4 +- .../public/hooks/use_redirect_link.ts | 7 +- .../public/hooks/use_summary_panel.ts | 13 +- .../data_stream_details_client.ts | 6 +- .../data_streams_stats_client.ts | 23 +- .../services/data_streams_stats/types.ts | 3 +- .../src/defaults.ts | 11 +- .../src/state_machine.ts | 305 ++++++++++-------- .../dataset_quality_controller/src/types.ts | 36 ++- .../state_machine.ts | 4 +- .../public/utils/flatten_stats.ts | 16 + .../public/utils/generate_datasets.test.ts | 108 ++++--- .../public/utils/generate_datasets.ts | 12 +- .../get_data_streams/get_data_streams.test.ts | 14 +- .../data_streams/get_data_streams/index.ts | 22 +- .../get_non_aggregatable_data_streams.ts | 9 +- .../server/routes/data_streams/routes.ts | 33 +- .../routes/integrations/get_integrations.ts | 18 +- .../server/routes/integrations/routes.ts | 8 +- .../server/types/default_api_types.ts | 16 +- .../dataset_quality/tsconfig.json | 3 +- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../tests/data_streams/stats.spec.ts | 3 +- .../tests/integrations/integrations.spec.ts | 8 +- 39 files changed, 610 insertions(+), 313 deletions(-) create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/selector.tsx create mode 100644 x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts diff --git a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts index 08313ddc4860b..5121f1b7f64d7 100644 --- a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts +++ b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts @@ -13,6 +13,7 @@ export const filtersRT = rt.exact( inactive: rt.boolean, fullNames: rt.boolean, timeRange: timeRangeRT, + types: rt.array(rt.string), integrations: rt.array(rt.string), namespaces: rt.array(rt.string), qualities: rt.array(rt.union([rt.literal('poor'), rt.literal('degraded'), rt.literal('good')])), diff --git a/x-pack/plugins/data_quality/server/plugin.ts b/x-pack/plugins/data_quality/server/plugin.ts index 4977e6f09a5c1..088905b8975d4 100644 --- a/x-pack/plugins/data_quality/server/plugin.ts +++ b/x-pack/plugins/data_quality/server/plugin.ts @@ -25,6 +25,20 @@ export class DataQualityPlugin implements Plugin { ['logs-*-*']: ['read'], }, }, + { + ui: [], + requiredClusterPrivileges: [], + requiredIndexPrivileges: { + ['traces-*-*']: ['read'], + }, + }, + { + ui: [], + requiredClusterPrivileges: [], + requiredIndexPrivileges: { + ['metrics-*-*']: ['read'], + }, + }, ], }); } diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts b/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts index a6c6754befb8e..895381703742e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { QualityIndicators } from './types'; +import { DataStreamType, QualityIndicators } from './types'; export const DATASET_QUALITY_APP_ID = 'dataset_quality'; -export const DEFAULT_DATASET_TYPE = 'logs'; +export const DEFAULT_DATASET_TYPE: DataStreamType = 'logs'; export const DEFAULT_LOGS_DATA_VIEW = 'logs-*-*'; export const POOR_QUALITY_MINIMUM_PERCENTAGE = 3; @@ -41,3 +41,5 @@ export const MAX_DEGRADED_FIELDS = 1000; export const MASKED_FIELD_PLACEHOLDER = ''; export const UNKOWN_FIELD_PLACEHOLDER = ''; + +export const KNOWN_TYPES: DataStreamType[] = ['logs', 'metrics', 'traces']; diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts b/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts index 74f0653396447..82d6d2651be56 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts @@ -5,9 +5,6 @@ * 2.0. */ -import { DataStreamType } from '../types'; - export interface GetDataStreamIntegrationParams { - type: DataStreamType; integrationName: string; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts b/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts index 1963c73d263e7..79fdbfbd7dd96 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts @@ -15,9 +15,6 @@ export type GetDataStreamsStatsResponse = export type DataStreamStatType = GetDataStreamsStatsResponse['dataStreamsStats'][0]; export type DataStreamStatServiceResponse = GetDataStreamsStatsResponse; -export type GetIntegrationsParams = - APIClientRequestParamsOf<`GET /internal/dataset_quality/integrations`>['params']; - export type GetDataStreamsDegradedDocsStatsParams = APIClientRequestParamsOf<`GET /internal/dataset_quality/data_streams/degraded_docs`>['params']; export type GetDataStreamsDegradedDocsStatsQuery = GetDataStreamsDegradedDocsStatsParams['query']; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx index 8c247104415cd..4c63b8480d3b7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx @@ -10,12 +10,33 @@ import { EuiSuperDatePicker } from '@elastic/eui'; import { UI_SETTINGS } from '@kbn/data-service'; import { TimePickerQuickRange } from '@kbn/observability-shared-plugin/public/hooks/use_quick_time_ranges'; import React, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; import { useDatasetQualityFilters } from '../../../hooks/use_dataset_quality_filters'; import { useKibanaContextForPlugin } from '../../../utils/use_kibana'; import { FilterBar } from './filter_bar'; import { IntegrationsSelector } from './integrations_selector'; import { NamespacesSelector } from './namespaces_selector'; import { QualitiesSelector } from './qualities_selector'; +import { Selector } from './selector'; + +const typesLabel = i18n.translate('xpack.datasetQuality.types.label', { + defaultMessage: 'Types', +}); + +const typesSearchPlaceholder = i18n.translate( + 'xpack.datasetQuality.selector.types.search.placeholder', + { + defaultMessage: 'Filter types', + } +); + +const typesNoneMatching = i18n.translate('xpack.datasetQuality.selector.types.noneMatching', { + defaultMessage: 'No types found', +}); + +const typesNoneAvailable = i18n.translate('xpack.datasetQuality.selector.types.noneAvailable', { + defaultMessage: 'No types available', +}); // Allow for lazy loading // eslint-disable-next-line import/no-default-export @@ -29,9 +50,11 @@ export default function Filters() { integrations, namespaces, qualities, + types, onIntegrationsChange, onNamespacesChange, onQualitiesChange, + onTypesChange, selectedQuery, onQueryChange, } = useDatasetQualityFilters(); @@ -65,6 +88,14 @@ export default function Filters() { integrations={integrations} onIntegrationsChange={onIntegrationsChange} /> + void; +} + +export interface Item { + label: string; + checked?: EuiSelectableOptionCheckedType; +} + +export function Selector({ + isLoading, + options, + loadingMessage, + label, + searchPlaceholder, + noneAvailableMessage, + noneMatchingMessage, + onOptionsChange, +}: SelectorProps) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onButtonClick = () => { + setIsPopoverOpen(!isPopoverOpen); + }; + + const closePopover = () => { + setIsPopoverOpen(false); + }; + + const renderOption = (option: Item) => {option.label}; + + const button = ( + item.checked === 'on')} + numActiveFilters={options.filter((item) => item.checked === 'on').length} + > + {label} + + ); + + return ( + + renderOption(option)} + > + {(list, search) => ( +
+ {search} + {list} +
+ )} +
+
+ ); +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx index 4ec200b1b98c8..66e2cba5ed870 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx @@ -10,7 +10,7 @@ import { EuiBetaBadge, EuiLink, EuiPageHeader, EuiCode } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { DEFAULT_LOGS_DATA_VIEW } from '../../../common/constants'; +import { KNOWN_TYPES } from '../../../common/constants'; import { datasetQualityAppTitle } from '../../../common/translations'; // Allow for lazy loading @@ -33,9 +33,16 @@ export default function Header() { description={ {DEFAULT_LOGS_DATA_VIEW}, + types: KNOWN_TYPES.map((type, index) => { + return ( + <> + {index > 0 && ', '} + {type} + + ); + }), dsNamingSchemeLink: ( ( + {dataStreamStat.type} + ), + width: '160px', + }, ...(isSizeStatsAvailable && canUserMonitorDataset && canUserMonitorAnyDataStream ? [ { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx index 7c3aea15a6cf1..a0875f1367705 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useEffect, useState } from 'react'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiAccordion, @@ -133,7 +134,10 @@ export default function DegradedDocs({ lastReloadTime }: { lastReloadTime: numbe { const { service } = useDatasetQualityContext(); @@ -22,13 +24,14 @@ export const useDatasetQualityFilters = () => { service, (state) => state.matches('integrations.fetching') && - (state.matches('datasets.fetching') || state.matches('degradedDocs.fetching')) + (state.matches('stats.datasets.fetching') || state.matches('stats.degradedDocs.fetching')) ); const { timeRange, integrations: selectedIntegrations, namespaces: selectedNamespaces, + types: selectedTypes, qualities: selectedQualities, query: selectedQuery, } = useSelector(service, (state) => state.context.filters); @@ -169,6 +172,25 @@ export const useDatasetQualityFilters = () => { [service] ); + const typeItems: Item[] = useMemo(() => { + return KNOWN_TYPES.map((type) => ({ + label: type, + checked: selectedTypes.includes(type) ? 'on' : undefined, + })); + }, [selectedTypes]); + + const onTypesChange = useCallback( + (newTypeItems: Item[]) => { + service.send({ + type: 'UPDATE_TYPES', + types: newTypeItems + .filter((quality) => quality.checked === 'on') + .map((type) => type.label as DataStreamType), + }); + }, + [service] + ); + const onQueryChange = useCallback( (query: string) => { service.send({ @@ -187,9 +209,11 @@ export const useDatasetQualityFilters = () => { integrations: integrationItems, namespaces: namespaceItems, qualities: qualityItems, + types: typeItems, onIntegrationsChange, onNamespacesChange, onQualitiesChange, + onTypesChange, isLoading, selectedQuery, onQueryChange, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx index 3a3475eabeeda..77764acae1e1b 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx @@ -48,8 +48,7 @@ export const useDatasetQualityTable = () => { service, (state) => !state.context.dataStreamStats || - !state.context.dataStreamStats.length || - state.context.dataStreamStats.some((s) => s.userPrivileges.canMonitor) + state.context.datasets.some((s) => s.userPrivileges?.canMonitor) ); const { @@ -66,15 +65,15 @@ export const useDatasetQualityTable = () => { const loading = useSelector( service, (state) => - state.matches('datasets.fetching') || + state.matches('stats.datasets.fetching') || state.matches('integrations.fetching') || - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); const loadingDataStreamStats = useSelector(service, (state) => - state.matches('datasets.fetching') + state.matches('stats.datasets.fetching') ); const loadingDegradedStats = useSelector(service, (state) => - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); const datasets = useSelector(service, (state) => state.context.datasets); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts index ddb116dc48306..f5ba4d01f8983 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts @@ -16,8 +16,11 @@ export function useDatasetQualityWarnings() { ); const isNonAggregatableDatasetsLoading = useSelector(service, (state) => - state.matches('nonAggregatableDatasets.fetching') + state.matches('stats.nonAggregatableDatasets.fetching') ); - return { loading: isNonAggregatableDatasetsLoading, nonAggregatableDatasets }; + return { + loading: isNonAggregatableDatasetsLoading, + nonAggregatableDatasets, + }; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts index a7de315a35895..f60a7914275be 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts @@ -18,9 +18,9 @@ export function useEmptyState() { const isDatasetEmpty = useSelector( service, (state) => - !state.matches('datasets.fetching') && + !state.matches('stats.datasets.fetching') && !state.matches('integrations.fetching') && - !state.matches('degradedDocs.fetching') && + !state.matches('stats.degradedDocs.fetching') && (state.context.datasets?.length ?? 0) === 0 ); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts index d83ad8299e263..b015d2335d625 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts @@ -47,7 +47,8 @@ export const useRedirectLink = ({ navigate: () => void; isLogsExplorerAvailable: boolean; }>(() => { - const config = logsExplorerLocator + const isLogsExplorerAvailable = !!logsExplorerLocator && dataStreamStat.type === 'logs'; + const config = isLogsExplorerAvailable ? buildLogsExplorerConfig({ locator: logsExplorerLocator, dataStreamStat, @@ -83,7 +84,7 @@ export const useRedirectLink = ({ onClick: onClickWithTelemetry, }, navigate: navigateWithTelemetry, - isLogsExplorerAvailable: !!logsExplorerLocator, + isLogsExplorerAvailable, }; }, [ breakdownField, @@ -181,7 +182,7 @@ const buildDiscoverConfig = ({ dataViewId, dataViewSpec: { id: dataViewId, - title: dataViewTitle, + title: dataViewId, }, query, breakdownField, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts index 622f495fc4774..ce8acd58b7507 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts @@ -19,6 +19,7 @@ const useSummaryPanel = () => { isSizeStatsAvailable, canUserMonitorDataset, canUserMonitorAnyDataStream, + loading, } = useDatasetQualityTable(); const { timeRange } = useSelector(service, (state) => state.context.filters); @@ -32,7 +33,7 @@ const useSummaryPanel = () => { }; const isDatasetsQualityLoading = useSelector(service, (state) => - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); /* @@ -42,8 +43,9 @@ const useSummaryPanel = () => { (item) => item.userPrivileges?.canMonitor ?? true ); - const isUserAuthorizedForDataset = - canUserMonitorDataset && canUserMonitorAnyDataStream && canUserMonitorAllFilteredDataStreams; + const isUserAuthorizedForDataset = !loading + ? canUserMonitorDataset && canUserMonitorAnyDataStream && canUserMonitorAllFilteredDataStreams + : true; /* Datasets Activity @@ -57,7 +59,7 @@ const useSummaryPanel = () => { }; const isDatasetsActivityLoading = useSelector(service, (state) => - state.matches('datasets.fetching') + state.matches('stats.datasets.fetching') ); /* @@ -70,7 +72,8 @@ const useSummaryPanel = () => { const isEstimatedDataLoading = useSelector( service, - (state) => state.matches('datasets.fetching') || state.matches('degradedDocs.fetching') + (state) => + state.matches('stats.datasets.fetching') || state.matches('stats.degradedDocs.fetching') ); return { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts index 55d21286d7f60..5f944bd3fcde7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts @@ -123,11 +123,9 @@ export class DataStreamDetailsClient implements IDataStreamDetailsClient { public async getDataStreamIntegration( params: GetDataStreamIntegrationParams ): Promise { - const { type, integrationName } = params; + const { integrationName } = params; const response = await this.http - .get('/internal/dataset_quality/integrations', { - query: { type }, - }) + .get('/internal/dataset_quality/integrations') .catch((error) => { throw new DatasetQualityError(`Failed to fetch integrations: ${error}`, error); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts index 35cd67a1724f9..1e75088853d33 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts @@ -7,6 +7,8 @@ import { HttpStart } from '@kbn/core/public'; import { decodeOrThrow } from '@kbn/io-ts-utils'; +import rison from '@kbn/rison'; +import { KNOWN_TYPES } from '../../../common/constants'; import { getDataStreamsDegradedDocsStatsResponseRt, getDataStreamsStatsResponseRt, @@ -15,14 +17,12 @@ import { IntegrationResponse, NonAggregatableDatasets, } from '../../../common/api_types'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; import { DataStreamStatServiceResponse, GetDataStreamsDegradedDocsStatsQuery, GetDataStreamsDegradedDocsStatsResponse, GetDataStreamsStatsQuery, GetDataStreamsStatsResponse, - GetIntegrationsParams, GetNonAggregatableDataStreamsParams, } from '../../../common/data_streams_stats'; import { Integration } from '../../../common/data_streams_stats/integration'; @@ -33,11 +33,15 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { constructor(private readonly http: HttpStart) {} public async getDataStreamsStats( - params: GetDataStreamsStatsQuery = { type: DEFAULT_DATASET_TYPE } + params: GetDataStreamsStatsQuery ): Promise { + const types = params.types.length === 0 ? KNOWN_TYPES : params.types; const response = await this.http .get('/internal/dataset_quality/data_streams/stats', { - query: params, + query: { + ...params, + types: rison.encodeArray(types), + }, }) .catch((error) => { throw new DatasetQualityError(`Failed to fetch data streams stats: ${error}`, error); @@ -59,7 +63,6 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { { query: { ...params, - type: DEFAULT_DATASET_TYPE, }, } ) @@ -86,7 +89,7 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { .get('/internal/dataset_quality/data_streams/non_aggregatable', { query: { ...params, - type: DEFAULT_DATASET_TYPE, + types: rison.encodeArray(params.types), }, }) .catch((error) => { @@ -102,13 +105,9 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { return nonAggregatableDatasets; } - public async getIntegrations( - params: GetIntegrationsParams['query'] = { type: DEFAULT_DATASET_TYPE } - ): Promise { + public async getIntegrations(): Promise { const response = await this.http - .get('/internal/dataset_quality/integrations', { - query: params, - }) + .get('/internal/dataset_quality/integrations') .catch((error) => { throw new DatasetQualityError(`Failed to fetch integrations: ${error}`, error); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts index 785cdb4a88ccc..ae1c72c23df0e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts @@ -11,7 +11,6 @@ import { DataStreamStatServiceResponse, GetDataStreamsDegradedDocsStatsQuery, GetDataStreamsStatsQuery, - GetIntegrationsParams, GetNonAggregatableDataStreamsParams, } from '../../../common/data_streams_stats'; import { Integration } from '../../../common/data_streams_stats/integration'; @@ -32,7 +31,7 @@ export interface IDataStreamsStatsClient { getDataStreamsDegradedStats( params?: GetDataStreamsDegradedDocsStatsQuery ): Promise; - getIntegrations(params: GetIntegrationsParams['query']): Promise; + getIntegrations(): Promise; getNonAggregatableDatasets( params: GetNonAggregatableDataStreamsParams ): Promise; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts index 87a6a398df8f0..d0b2b9978080a 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts @@ -14,8 +14,15 @@ import { DefaultDatasetQualityControllerState } from './types'; const ONE_MINUTE_IN_MS = 60000; +export const DEFAULT_DICTIONARY_TYPE = { + logs: [], + metrics: [], + traces: [], + synthetics: [], + profiling: [], +}; + export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { - type: DEFAULT_DATASET_TYPE, table: { page: 0, rowsPerPage: 10, @@ -30,6 +37,7 @@ export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { canViewIntegrations: true, }, dataStreamStats: [], + degradedDocStats: DEFAULT_DICTIONARY_TYPE, filters: { inactive: true, fullNames: false, @@ -44,6 +52,7 @@ export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { integrations: [], namespaces: [], qualities: [], + types: [DEFAULT_DATASET_TYPE], }, datasets: [], isSizeStatsAvailable: true, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts index 7ce3c5b5d8f60..127e56a755c86 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts @@ -9,34 +9,43 @@ import { IToasts } from '@kbn/core/public'; import { getDateISORange } from '@kbn/timerange'; import { assign, createMachine, DoneInvokeEvent, InterpreterFrom } from 'xstate'; import { DataStreamStat, NonAggregatableDatasets } from '../../../../common/api_types'; -import { Integration } from '../../../../common/data_streams_stats/integration'; +import { KNOWN_TYPES } from '../../../../common/constants'; import { - GetDataStreamsStatsQuery, - GetIntegrationsParams, - GetNonAggregatableDataStreamsParams, + DataStreamDegradedDocsStatServiceResponse, DataStreamStatServiceResponse, } from '../../../../common/data_streams_stats'; -import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; +import { Integration } from '../../../../common/data_streams_stats/integration'; +import { DataStreamType } from '../../../../common/types'; import { IDataStreamsStatsClient } from '../../../services/data_streams_stats'; import { generateDatasets } from '../../../utils'; +import { fetchNonAggregatableDatasetsFailedNotifier } from '../../common/notifications'; import { DEFAULT_CONTEXT } from './defaults'; import { fetchDatasetStatsFailedNotifier, fetchDegradedStatsFailedNotifier, fetchIntegrationsFailedNotifier, } from './notifications'; -import { fetchNonAggregatableDatasetsFailedNotifier } from '../../common/notifications'; import { DatasetQualityControllerContext, DatasetQualityControllerEvent, DatasetQualityControllerTypeState, - DefaultDatasetQualityControllerState, } from './types'; +const generateInvokePerType = ({ src }: { src: string }) => ({ + invoke: KNOWN_TYPES.map((type) => ({ + id: `${type}`, + src, + data: { type }, + })), +}); + +const isTypeSelected = (type: DataStreamType, context: DatasetQualityControllerContext) => + context.filters.types.length === 0 || context.filters.types.includes(type); + export const createPureDatasetQualityControllerStateMachine = ( initialContext: DatasetQualityControllerContext ) => - /** @xstate-layout N4IgpgJg5mDOIC5QBECGAXVszoIoFdUAbAS3QE8BhAewDt0AnaoosBgOggyx1gGIAqgAVkAQQAqAUQD64gJIBZGQCVRAOQDikgNoAGALqJQAB2qwyJOkZAAPRAFZ77AEwAWAGwAOXfc+f39u7uAIwBADQg5IieAMwAnOwA7PbOujHucTHpzs72AL55EWiY2HiEpBQ09EwsbJzcpfzKkgBizQDKABLSYuKieoZIIKbm6Ja01nYIzu4xLv4ZMcGJwZ7OiXERUQieronsurtxibquufYrMQVFDTgExGRUdIzMrBxcJbzsAGY4AMYACxItCgfAgdDA7GBADdqABrSHFHhlB6VZ41N71T7oWA-f5AkEIGHUP4YcYDAbWEYWKxDKbpJwxNJZHIxHK6DKJLaIYI+fauTzBeyuOLOOKuGKxK6FEBI0r3CpPaqvOofZG437oQHA0FsJgcYxEDDfagMAC27Dld3KjyqL1q71uOLxWoJUCJtFhpLGdApBipZhpEzpiD2nhccVWx2CwVch1W9m5Owy7HciT89klIr2rnyMqtKMVdoxqrAUAYqAgkGQJP4wl6MnkSmkqk0On9Q2pPuDoCm3nc7F26aynLOIqTsQSyVS6Uy2Tc11lToVtvRKveZYrVYgNb+TVaHW6vX6HZMge7kx5umWB3WYaynkSMWFE-czlTrj2s2C6yf9mCi4FiuaLKg6nCbpW1a1i62ogmCEJQp68KIsuNogfamJVuWkE7tBmqwe6xLeuSBiUp257jJeCAxiE7AeOmJzPokzF7EmvIXHRgrCqK4qSlkgGoaiSoYaW2HbruGr4jqfB6qa7CGsapoWkBaHCSWG5iVBe4wW6HpemSvqkaewwUbSvY8ss+zXnEsShB49iRlykSIHEhzzMxKQ-s4ni+HmNzYsBanroh6AQd2dYiBIjaKCo6haGRZ6jJRIYIMKqarMsbIhB5QqJs5CCfq4g4xs+nkhDEEruAJAWqcWwXAqF2HhXwzRtJIXQ9BIJ6DIlQZUTkRWZisiQij5qzuBySbOEK7AXCNwTHLxqQpNVyKBXVYENWF4wRQ20hyGoUgaKo8gAPJqO0CUmUlZm2A4HGxJ+Sz+CsDl5dsoRON4mRxvYPgcuKq3yrVa6bfQ210LtUXSGoohKO0QiiJQ7VXV2yXmalngJEyMTDXEKQCksU1pi4cZY2moRzq4QPWkJG2YltTU7YIkVSNIuACJIygAJqo6ZPZ3dRqxFRkszJFluPLGxGzsDZv7pCscbrH5S41XToMM+DTOQzp0ngrQkLEgilqCUWGt1IzFbhbrhJEQZtB+j1119Slua6IOzE+VmPhvm4Sa44yey6AxyzTb4NOFquoGa41Vs7TbuoMPq8lGugJrmibatm9HFta3HOv4bpdvdo7AY3QL9K8rNcTuAK3ixgKyRJoE7t7AHkZxKKDlVfmptRyJHCW-buJENQOEs3tfQAEIADIyJQyhyFIi-dWXLsY2m4a8Y+-7LJvSYTYNWQ1xkFyPjMEfrebg958P7Cj+P4inRoGhz-tsOUPIABqMjHu0kjiEusZNGt0+wzHYBlUUWNj4XFcEmCU+w2Q-lnP4T8mRL4gxzjfWOd8H7bj4E-F+b8WgCBnjPTqfR-7iBhnDFGwD+ZUUFPsea14BS6EyFGf26ROKhw5FjDwAoVYqXVlgn4RByDUHwOgPg-856fxhpIAA6hQ0QVC+blyoimdhvgTiZmcFkBBbEKpFSfN5ZIwQ2S42pr3LO-d1JiIkVIvglAZ6nX-tIFoM9uanQEOIdR69Bb-icJ+RwARYysifEY0IsssZ+A2KcCqmYMEiIHg4yR6BEIWAeAALz1ghWAmBQqZzWpg1J3xxHpMyWMHJOp-EXhSryGacZEj6O8p3XGxw2L4zmMkGywpprDXWMk7OZSKlSKqSQGpIIsSoHaIwMAqAzTIBwKgEgRBJKujyQbRCsJjbCJGfY8pjiMnAiyaQXJ0y1RzIYAspZKy1kbIInpEk9tS7kQ0a7fRqYVhYwWv+XMViuluHYLjYx6xBTsk8MMuxwUjmVNOdU85OoZnXNucszADyE4ySTnJBSaclLFOBikw5YyTm0DOSQC5UAUXzMWei1Z6yE7POIoZfQdT0aCzOMEJI2jryxiCaKJyH10xTl4r4fwPhhSJGhehElxyJlTOpUPbsaBYAAgAEZjwYBAR5bp4LbKNihWxsrYWkoVUi6Zyrxiqo1VqnVTLi4kTZfQj5GM0EuCWN5NY1k1h+3yjkRwEDQ4BAmiOR8MqgpgTheMhFkyLVKtviqrAtrUDat1dJWSBpU7p2Un3E1UazWxsVSFCGtAbWatTfawuOpmWvKMk7EBFdQwig9T+PwqQFq+rgf60I74rEXF0OsTIpwI30zqNGjJeDIDONce4zx3jfHstAYgEaCQT6jWWjmZwbE9hODFKHY4iwghQpsSU4lpr5VTogBPaGB12hyA0J0QBsgYotjiu2BtDCGmdoOEybR4TDjMTYrA1MQRUjBxrrkLwo7r5pPGX8Ue2Br2nSEJINQHivE+L8S6gJUxwUQIqsxNMMxEi13SDumuBx-D40fKcE4J6ZS0GoFWeAQx9kwodGvepGMAC0rhuWSlWCRyUA1djvUQDxre00cwZE-LoYO-gYOiLVI0LjHKpj7DcF4HwfgQ0hHCPlacIKFhiiyJKR81j-JnoOcFFTXxq0gjU8uoW4Z5O7DSIKSUswBRJnFAOLIvhPwzElhkJTqS7POivU5ptqVwFCksSJiU-Hgi+Z8rNGYf0mR-XWOkML9isJbi0qx3q3HBbJHDEOKUo43CbEMykYzYG5zmZGnl2zEFxJ4Sko595uHoiRlmvxxwrkuInBS-lY4744n+FCN4Ea6ZWtgQKzhCS98x7bmi1RCxaW1h6Nco4CqaQ2LXjmMRxw15DhsmFAtmOpbivO1K1MAcIQmFZUskE8TCB0x0QlJkMUPgDFLGu7nHB1sHNQA2w08USRYi128Bmc+7gppQ8Ysgi434fJCLzZGm72taAjzW5ACHG8zgQN8KESUwdgtCocDkA4AQRTsLo14OIQOOATqJ2Vun9FZwnDTHNtiOQEhvk-N4JkHheTOFZ3BslFKqUc6mIGjk3POQcg8mxEITgOQVUFIzrMlnVbWY45iCd5rKXIqubSu5GL1ny6vHMJYsxIyEfxtNRH+VliDrol63TrkYz4ylybot8aaU3LpfcxlYPbfUX-CC8nTu9gu9CGxXYRVTiOVmFxbykvT1EpswW+VQezeXO4KisP1vcT6zAFH0+ECctCkjOcIIyeHLfN5LsGM00KrZ6s7no347C3ksRUXhNIPrXJorWmqPvI5hK7TDz1XTd-XB01+w1YLT4isIDwP2XyKrV0HLXa9N3WSvqZ5DH2fT4Vd84+wMkxPFO4zjTD3HvtM8-G+30PqlJbccH8rRXiEUepG7sYGmYFiwoSCMQU0C0rcsYrkiwZwawW+l6BOEAU+wc3KHCjEaOYoQG7ugQCQ-gHawW-GsQ3eBuve+a7+8qCGZghOPWD290A44oLSg66+2YkB7uEo742iTIywvgg6K0BQeQQAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QBECGAXVszoIoFdUAbAS3QE8BhAewDt0AnaoosBgOlk3VnYgyw5YAYgDKAQQBqAUQD6ycQBVxoxQCVp4gLKzVS0QG0ADAF1EoAA7VYZEnXMgAHogCMANgDMAdnYAONwBMbgAsAKxh3kYAnL4ANCDkiMHBHsHsRgG+vh4xIb6hLgC+hfFomNh4hKQUNPRMLGyc3Lz85ULCAHIA8ooAkgBiAJrySirqmjp6iqKy-eK9ADLSyMZmSCBWNuh2tA7OCO7efoEh4aGRMfGJCCkevunBLsmBOQEeHsWlAhUExGRUdEYzFYHC4GBa33aAFUAAoKRRyPpaORqcQdADi0lWDk2tns632hx8-iCYQiXmicQSSQCwQC6XCRlCQRcHjcLlCnxAZUElT+NUB9RBTXBfEhPGEGn6GlEAAkRspsetcdt8aBCZ5iScyecKZdqTcXFEXOwvC5zXcjMEvMFfEUStzxb9qgC6sDGmCeHwwFAGKgIJBkNQAMYiCQyeTSdGo5DLeRdSgzKaGUw46x43YE1ya46ks4XKnXYJRUJRdieKJ0sJRY0FLk8n5Vf61IENUHNb2+-2BkMibp9IaR6PiWPIeOJ3TKaazeZLFap5Xp1WZ9XZo4k07kylXJJuPfsKJeLLsm1eUJW+tOpsCt1tkVegNdgMQIOhzo9AbDWPD0fjpNTmY5kWZYDBcNZLCXHY9jXLU8y3fUi38Dxy2ZIwPGiLwPHOD4HQbHBnWbQV3XbUVHz9Z9XxEWF4URXpkVkVEMSxBcIK2KCswOHMNx1AsdxuLw3B8Pdgk1VIvFrS82j5F0WyFD0OzI7sX17SVpGlaQ5QVcQlVYjNoM49dtXzPVCySM0fA8AIXC8AIAiPay7Uk3kCJvVthU9XhaDocQoF9H0BAAI1YPCJXDORug6WRxHRaMo1GAAhJYtNEaRph0jZILVJwYNzTddW3A0cn8dgglCUJskPDIjScxt+VdNz5NFLzaB8vyoEC4LxT7D9BwiqKYo0dEEqS+EVFSwDZxAliMrYrKNUMuD8oQxBvByErizcNDfCiTbMhq-Dr3quSSK9ZrWoYfzMCCsAQu6gdhj66LYqG5RErkUaUunIC51A8CZr0jiiVyniTL4u4oiMEr7Ih1IRKMIwvH26TCNvdyOzO3yLvaq7Oqkqi4SUWj6MYzF0pVdjVwM2C8t4wqKoPLDvErHaUn8JGXKO4j7087zMcu1Brtu1T1M00aycyldsqp4HjIK65vG29hS1pEIonQ9DOVwq86tkrmSHoH0-WXfGaNkJEUTRUnpvJubEEPPiRJs9gIjso1fAyNwonZw7dbvfX0ENjAdhEKUZXlMXrYl-T7YNETbPYc00NCG0nlZNxvZ1oi-YNrtjeEajCdkXoOgRYc+i6DoUz+m3Jf2GOiyNE0Nb3EI2RtAIM5krPhX9wO84LhFZA6bQNJhcRKA08XZtru2vAdzIfACNWjE2le3nTrWpI532e5zo3g-zgnB9wKFxAWXo+knyPp+jufY7uZDMitc43F8cTxM7lGGo4Xvc4PgfESDBhFfauUdAYuDtM7ZIh5X7WXcA7SyyFHi0m2mhJeWRP6uWOuwX++86Am0LifaQahBhTwBpTKI8dKzRAyDtSyKcHYZFCMcKqm0vA2gKB3Tezkfbd0aLgoO+D2AADMcDBgABb6ygMICAdAwA4NoAAN2oAAa3kSFbefCf570EbQXgoj0ASKkQgfWyjgy6NWGQ5c+lQivz8FkCB8MV55DvkWZkbhTQp3POeBGGDuG1S7qjfhOjjYiLEZI2g0i2BMA4BYIgGBhHUAYAAW3YBo3hQTtEBz-kIgxRjIkmKUSGCxpgrEUylrY+4WQ7Tu3hsJN+DsQgeOSC4IwRoFbMi9v4g6mdMkKOyXgvR7AiDUCUofU2r0kqUDUBfYhvRtLX3IVLfwZZbRGF8LaM0ENHhRAduVNIZU1ZL09hkFImDObZwGbo3gIyxmKC6DFJKxdx59AjB9caZTbYIHyCacIFJrSVjPN4FwDsRImm2lhcS1pU6ay+FvDJ39+l92DsM0Zz5hD3MeXIfoUIFgLGSqlIeI8q5phvhxDZyFWnMzXm-CBrikhsmYRDdk+QNnJ0POcnejRhFEHINQfA6AxDSCWJQRQQ9pAAHUCWKE+TPBANkwYligTWVkNY7R2Q3nCnhvTEU8r5QK4QlAFhdBSrMBYgwuhQhlYs6xHEFUGlpMhN+ORwiPAVncWFjp4U6uwXq-l6AFG2D+AALykTIuR951Ha0Cbq3l-rA3bBDVI2V+lWS0gPBA4IGRLLlTcOVPitI0KmnXiWV+JZHLdORlgrmfqBUJpIEmyJ7AMZtQ6jdcUYTDEROkbI2g8jTGqKjd6mNvq411v1kG0goam0tqxm2kKnb8lQEKWYkpJgU0cQ2ukM0WQSwFCwpkPiTxKwlVsUedeAkbI4S1QEr+o79UBonYmqdUjm281bTjdtUlF3duENEpJ7A4kJKSak9JPqa1jsfbQSdJBp1QDfS1Pm2MBa415D+4xA7zHLksTa8p+wt0IwgdtMqrJmSmQOOVReYQjR0nEoeIInKtEiMg-Wxt8HZ380Fh23tYBxmF2LqIXo6JZTTnNgxS2zFQFkspsyZhZ5X6+CXmmtW9LOLuxKu8Ta7JKF2XeIxvptaoMwbgwh86nHUMVD4HIoVIqxXvOtVJpZ+xPBpCtBDCkR4UiljcEeoqJVPZ0prGeSs9ob09JHRBh9rGX1NtaKgUQjAwCoGSaIHA2xIn6PCWGnjCjlFqLSdGu9kX41PobTF+DcWEsXWS6l9A6WoCZa7RhopWGdg4cc7aymdJ7gcmqW07wbDggFreCaMIngl42jQp5-TsaoulbY2KTAVWkspbS1IxrS6-0MBiYB+J6BEkpIK8Oord5DPRdg6+yriWatrYy+hgpmG10bq65kBO5Usj9YEgjIbDrLJpGSNaR4eaggf0rZogzLH5vlcW-F67q26vrfO8GsAvQQkooEcuZAOBUAkCIBt39OWB35bAxF07kPoPPou7FgQy2bsI7u1D2DKO0dCIxzsLHmBcf4+a6u7DpTcNfLIweEITi0KCSyKEAttL2DvBsoJR4GzFczfvSVinZWqcVZp3D2r9XeCM+R6jq5oS2d0A5zjvH92onbYA0B-bIGjvatJ8KM7+vLta+q-D3XSPmdG-Ryz2gZuueW5XcUvn66BdyqFyzUXbcJcFvYfcVIEuyor0zcr4r461cLaux7nXiP9c++Raz-3aBYDiICqMhgEBueRPDX23Lg6He3urWTubWfoc55W3nhn7emeG6L0Mk3AesDl8r9X4Pj2w-PYqVmhOGzX6e2LLkVTHh3AePYW8MqyCKQr3T631Xxm3dLe17dhr3v+85MHyXkfFfUBV5r1bnbtuDugcKy3535PD-U+P7n0-eve8G7+7-6+6m435j4P4h6tZ0DtakpOaICMhz4iQrJL7+Ar4BClimibQHoRDmiIxg4Ioq6Z5f6a4-5d5-7n5AFIqX6l6j537j55K-r-qxJ7Yv5N7hYnYf5t7EEw606e754AGF6X7AED40G3734T4tZPZgSwGdYz6QyZoL7MzL5gwIzIRHg5BebwxZoIx76cEH6U4mad7JaB4W4MHZYRpE5DqO4cHcqf4GFH6w4e4mEQGT5tb84dZ4YMppBsgQzZABArwryVgeBHpGjMKKZLxvAtKKbRC6G2FcH2Hf6OErbOGW5bZP4sH24k42EcAu4AEOG8EpFmEPaSFT4R76QpDeEnJ+EBGL7BEGiJz0jZDUYchLyoShZerWHv5xH6Hq6GHu7JHY5B48Z8aDwCZCYiYzBiYkySYyGeE3CpAy5VGWQ1FBFHp1J+DQrWQwwQxcJhZVoXJ6FEEJEkFJHGGDEW7DHxQaDiAADSyAXQEqkU-QvQwqY4lAsoEm0++wJISs9G9C7Ir85wIRRa2QnCKQvhiCsRORdhvR+RcOWOT4kA-QJAYARA9BWWtehORSxOb+Bx3RRxsJiRBRgcz4yJqJ6JTWxRvObh4eHhgu0QwupY1CWQ7CLg6BR6MQJoLcea0QVkIQZy+B4G++BJ2e-RZxiJEAZJaJD+aRNuGRh2WRXR0J8RhJJxxJEpUpFJS6kBT2ZRHE54ZYO0TJWaLJZo7JDq32KEIkAKgQqeUJzGKpoppB4p5ESJKJ0pVmfaIxcgYxwmomdEFsTEXx8B7wCcERbSdIh4O0qmRGzCgkEMtiJGiZeBex4Os2PRTppxySCJrpkp7p4+wxACQ4MYcYzxrxkx4gb0sg0ysyMyCydJcq2QkMX2rSym6ynsHJDJ7CycqhlYSB16HRzeeJypGZ0OWA2ADA6A8U1WKisiAA7rQJqb0LANIKGKkViXllYUOVyiOSKWObABOVOTOfOYufmcuauS4SUTScGTcIJP5naJhGVJkAUGeGDH4X4DulaO4AUHWIKU7viUZscewOOWwEeUlrOdQAuUuSuWuUUY-nKcBgqbiTuQ6aORrsBQeaBdOeBSedBReRIdSdAe4bMV8o7PedZFhGRi+ZLoVJhGWFkO8DplRe0YqcOahXWrcuikaiatiuapag5iRXKpQnxDZP9qtAjC8BwimYOewUqexQGsGCMtgBAMIF0MAk8XxVajeT4QePDGaSDqgjRdcOgSaKWlZDuucBAqkMUA6F5AGPAOsKxTuYJfpAALS2J8R2IljsLeC2Tz7hC+D2keQuWAzhDgpGTwTkZYSeBKyEY7TOoAmepOVMYeQw4VAOW6SyGEjlT0URVLTkaPBWinoTbBblSMpBUKRdSW4hWUxGhHglSKaJnuzWi0hGVJBGhlh3DQr0auosXIUpWVV4yopKQ1VSx1X3CZDoF5rNWiVtXzF2K6gg7PBqxhAVWkQkk9ihijXZWKzcSyzLQ3DJz3CL6ljwzZCvxrUPgbXKSwUYlQDbWIC2RtKmhvzxUcjwzGiqbWjZDlgnDuBZriS7EyX7EoWpWKQUS9jDXPgPUIBPUmhHjiSwI+KfUOwxD3AwLlShHJzsiXUtDXWUTsD4C0CoACriJJJM4QAw1w0vWI12jI3WSNL7gtFNIPmMy42mZIbzpdQw29a5WLS0zyw8mMnoFsgIxLzs0cbIZcZDVwVU3oGGmHLeJHjnABBvmhnmitKCTuCslJX9V9KpWS1c1DWcWQBy0YF7olhMjK2WSMIZD+bRXqwZCRES3vpzqfq3SE3E2k3k3I6U2LjSZSy2Tm2K1W35A220V3DOyRFPBMgQrWj2lD4ZX-RZVJC7KxytJOrWibSVToSewJ2UGy3+1wEICy7lgli2RL6eCr4-ZFh5o+BPAbSZDbQ1hA3JV9KJ1Q2m1F0p0IDUJKzlTnDwxnAQqNL5BKyOxvCr65ocj2mGYw2uXkYcjNK80CTuwNGt163pl7ka4w1Zp8TZCmWr5aEpB5oBWz0wkLaG3u3igw01i+atJ+AWiMxhV8nn2OnQ5X0oZfpoaF2ZVzFPAxl0iUpXraYxBGlv1oUmaf3S1oY8Yw3ZCJ5vw2SULuw2TsJHrMhNwvxZpNIFB7gQPb19HOl8EZbwPkZWQpAHgxDWh6gnKarA1pmEGAWqk8En705n6-3J3-3WjDaUM7QAm+XeCbIEPMOZm8Hd5n4F4X6DJJ01yppsgFpYHOz0J3CezoQljBAiNI5wm-7sP-7GaCEyNUGDLOE80bKKMQx+DGjwyZCBBmgz1-nZHyXaNElsNe5SOUFD6FF3VU3h3GXiSQysqKYJ5tKKZaOu6uO6PuMCHSPXLGO6IpFwPd1zGKbIRWiFr0ab5S4rxKwWhPCK2sgDlt1b2iMd5ikkOSMxOePX5l5iHV5mM12PW5Ay5TXiTvC+IiThN5GRNkF6MUEgFX4DOiHgHVXJNfJvCq2FTRBIJPBvxWgCTgOONyW5HcFGEVP6MGGGNxNeNgF0EtByI81nUy5hBWSZAljoS0hgytkHjWlMKLUlhdOrPlMSMbO9FbPG41O0HiFE0k3oBk0MAU2HPrLHOYNnOD2XOFToE+AVFNItzoSYSPNAVrMvOelgA82BBgwKxR1o2YSnhmiIssNrOmNjNCVp3XDGidWoLsjWRO1hNLNsUrNIvlPeOUn3Ukupo8P1EezFpnia3JArwbIEtiPwnnH7N9ow2YQeI1g1i2KMUpAM31Fsk+DrL+GWS7pbSaP0soWMuEvMvXWamyNgIUJkuuDiQTX+GA13A0YcpatMY6vCtOH6v5kP482cvXBGhMj93eXWg9lGj0PFNMMuNqkisanOuou32QLGgpDvx03z4FptLNlV1tICRkjSUBsZ6lPoUgWTnYWoAQVQVnkwWGsB2EhGhgzA5R2cLux+FYRCv7mHm5v5unnknnm3Wsvosr5nj0g5CWRBDry2R9XHbLMX31tYXHmQXNtomttitovst2ohCmizPUuoRRWr0fnRmshMKr5pub2Bsm1+1-1fJPBrR0jYSK6UI5CqZvCHjpDCQjatKYSDudEMssaKXWBd2Htyp9vljWmNzIOWQliKP13+EkjGhuz8M2WFBAA */ createMachine< DatasetQualityControllerContext, DatasetQualityControllerEvent, @@ -48,66 +57,105 @@ export const createPureDatasetQualityControllerStateMachine = ( id: 'DatasetQualityController', type: 'parallel', states: { - datasets: { - initial: 'fetching', + stats: { + type: 'parallel', states: { - fetching: { - invoke: { - src: 'loadDataStreamStats', - onDone: { - target: 'loaded', - actions: ['storeDataStreamStats', 'storeDatasets'], + datasets: { + initial: 'fetching', + states: { + fetching: { + invoke: { + src: 'loadDataStreamStats', + onDone: { + target: 'loaded', + actions: ['storeDataStreamStats', 'storeDatasets'], + }, + onError: { + target: 'loaded', + actions: ['notifyFetchDatasetStatsFailed'], + }, + }, }, - onError: { - target: 'loaded', - actions: ['notifyFetchDatasetStatsFailed'], + loaded: {}, + }, + on: { + UPDATE_TIME_RANGE: { + target: 'datasets.fetching', + actions: ['storeTimeRange'], + }, + REFRESH_DATA: { + target: 'datasets.fetching', }, }, }, - loaded: {}, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'datasets.fetching', - actions: ['storeTimeRange'], - }, - REFRESH_DATA: { - target: 'datasets.fetching', - }, - }, - }, - degradedDocs: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDegradedDocs', - onDone: { - target: 'loaded', + degradedDocs: { + initial: 'fetching', + states: { + fetching: { + ...generateInvokePerType({ + src: 'loadDegradedDocs', + }), + }, + loaded: {}, + unauthorized: { type: 'final' }, + }, + on: { + SAVE_DEGRADED_DOCS_STATS: { + target: 'degradedDocs.loaded', actions: ['storeDegradedDocStats', 'storeDatasets'], }, - onError: [ + NOTIFY_DEGRADED_DOCS_STATS_FAILED: [ { - target: 'unauthorized', + target: 'degradedDocs.unauthorized', cond: 'checkIfActionForbidden', }, { - target: 'loaded', + target: 'degradedDocs.loaded', actions: ['notifyFetchDegradedStatsFailed'], }, ], + UPDATE_TIME_RANGE: { + target: 'degradedDocs.fetching', + actions: ['storeTimeRange'], + }, + REFRESH_DATA: { + target: 'degradedDocs.fetching', + }, }, }, - loaded: {}, - unauthorized: { type: 'final' }, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'degradedDocs.fetching', - actions: ['storeTimeRange'], - }, - REFRESH_DATA: { - target: 'degradedDocs.fetching', + nonAggregatableDatasets: { + initial: 'fetching', + states: { + fetching: { + invoke: { + src: 'loadNonAggregatableDatasets', + onDone: { + target: 'loaded', + actions: ['storeNonAggregatableDatasets'], + }, + onError: [ + { + target: 'unauthorized', + cond: 'checkIfActionForbidden', + }, + { + target: 'loaded', + actions: ['notifyFetchNonAggregatableDatasetsFailed'], + }, + ], + }, + }, + loaded: {}, + unauthorized: { type: 'final' }, + }, + on: { + UPDATE_TIME_RANGE: { + target: 'nonAggregatableDatasets.fetching', + }, + REFRESH_DATA: { + target: 'nonAggregatableDatasets.fetching', + }, + }, }, }, }, @@ -168,45 +216,15 @@ export const createPureDatasetQualityControllerStateMachine = ( target: 'integrations.loaded', actions: ['storeQualities'], }, + UPDATE_TYPES: { + target: '#DatasetQualityController.stats', + actions: ['storeTypes'], + }, UPDATE_QUERY: { actions: ['storeQuery'], }, }, }, - nonAggregatableDatasets: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadNonAggregatableDatasets', - onDone: { - target: 'loaded', - actions: ['storeNonAggregatableDatasets'], - }, - onError: [ - { - target: 'unauthorized', - cond: 'checkIfActionForbidden', - }, - { - target: 'loaded', - actions: ['notifyFetchNonAggregatableDatasetsFailed'], - }, - ], - }, - }, - loaded: {}, - unauthorized: { type: 'final' }, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'nonAggregatableDatasets.fetching', - }, - REFRESH_DATA: { - target: 'nonAggregatableDatasets.fetching', - }, - }, - }, }, }, { @@ -280,6 +298,16 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), + storeTypes: assign((context, event) => { + return 'types' in event + ? { + filters: { + ...context.filters, + types: event.types, + }, + } + : {}; + }), storeQuery: assign((context, event) => { return 'query' in event ? { @@ -292,42 +320,37 @@ export const createPureDatasetQualityControllerStateMachine = ( }), storeDataStreamStats: assign( (_context, event: DoneInvokeEvent) => { - if ('data' in event && 'dataStreamsStats' in event.data) { - const dataStreamStats = event.data.dataStreamsStats as DataStreamStat[]; - const datasetUserPrivileges = event.data.datasetUserPrivileges; + const dataStreamStats = event.data.dataStreamsStats as DataStreamStat[]; + const datasetUserPrivileges = event.data.datasetUserPrivileges; - // Check if any DataStreamStat has null; to check for serverless - const isSizeStatsAvailable = - !dataStreamStats.length || dataStreamStats.some((stat) => stat.totalDocs !== null); + // Check if any DataStreamStat has null; to check for serverless + const isSizeStatsAvailable = + !dataStreamStats.length || dataStreamStats.some((stat) => stat.totalDocs !== null); - return { - dataStreamStats, - isSizeStatsAvailable, - datasetUserPrivileges, - }; - } - return {}; + return { + dataStreamStats, + isSizeStatsAvailable, + datasetUserPrivileges, + }; } ), - storeDegradedDocStats: assign((_context, event) => { - return 'data' in event - ? { - degradedDocStats: event.data as DegradedDocsStat[], - } - : {}; - }), - storeNonAggregatableDatasets: assign( - ( - _context: DefaultDatasetQualityControllerState, - event: DoneInvokeEvent - ) => { - return 'data' in event - ? { - nonAggregatableDatasets: event.data.datasets, - } - : {}; + storeDegradedDocStats: assign( + (context, event: DoneInvokeEvent, meta) => { + const type = meta._event.origin as DataStreamType; + + return { + degradedDocStats: { + ...context.degradedDocStats, + [type]: event.data, + }, + }; } ), + storeNonAggregatableDatasets: assign( + (_context, event: DoneInvokeEvent) => ({ + nonAggregatableDatasets: event.data.datasets, + }) + ), storeIntegrations: assign((_context, event) => { return 'data' in event ? { @@ -341,7 +364,7 @@ export const createPureDatasetQualityControllerStateMachine = ( }; }), storeDatasets: assign((context, _event) => { - return context.integrations && (context.dataStreamStats || context.degradedDocStats) + return context.integrations ? { datasets: generateDatasets( context.dataStreamStats, @@ -388,35 +411,49 @@ export const createDatasetQualityControllerStateMachine = ({ fetchIntegrationsFailedNotifier(toasts, event.data), }, services: { - loadDataStreamStats: (context) => + loadDataStreamStats: (context, _event) => dataStreamStatsClient.getDataStreamsStats({ - type: context.type as GetDataStreamsStatsQuery['type'], + types: context.filters.types as DataStreamType[], datasetQuery: context.filters.query, }), - loadDegradedDocs: (context) => { - const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); + loadDegradedDocs: + (context, _event, { data: { type } }) => + async (send) => { + try { + const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); - return dataStreamStatsClient.getDataStreamsDegradedStats({ - type: context.type as GetDataStreamsStatsQuery['type'], - datasetQuery: context.filters.query, - start, - end, - }); - }, - loadIntegrations: (context) => { - return dataStreamStatsClient.getIntegrations({ - type: context.type as GetIntegrationsParams['query']['type'], - }); - }, + const degradedDocsStats = await (isTypeSelected(type, context) + ? dataStreamStatsClient.getDataStreamsDegradedStats({ + type, + datasetQuery: context.filters.query, + start, + end, + }) + : Promise.resolve([])); + + send({ + type: 'SAVE_DEGRADED_DOCS_STATS', + data: degradedDocsStats, + }); + } catch (e) { + send({ + type: 'NOTIFY_DEGRADED_DOCS_STATS_FAILED', + data: e, + }); + } + }, loadNonAggregatableDatasets: (context) => { const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); return dataStreamStatsClient.getNonAggregatableDatasets({ - type: context.type as GetNonAggregatableDataStreamsParams['type'], + types: context.filters.types as DataStreamType[], start, end, }); }, + loadIntegrations: () => { + return dataStreamStatsClient.getIntegrations(); + }, }, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts index a03bddcc9e93e..624fef066afcb 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts @@ -6,18 +6,23 @@ */ import { DoneInvokeEvent } from 'xstate'; -import { QualityIndicators, TableCriteria, TimeRangeConfig } from '../../../../common/types'; import { DatasetUserPrivileges, NonAggregatableDatasets } from '../../../../common/api_types'; -import { Integration } from '../../../../common/data_streams_stats/integration'; -import { DatasetTableSortField } from '../../../hooks'; -import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; import { DataStreamDegradedDocsStatServiceResponse, DataStreamDetails, - DataStreamStatServiceResponse, DataStreamStat, + DataStreamStatServiceResponse, DataStreamStatType, } from '../../../../common/data_streams_stats'; +import { Integration } from '../../../../common/data_streams_stats/integration'; +import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; +import { + DataStreamType, + QualityIndicators, + TableCriteria, + TimeRangeConfig, +} from '../../../../common/types'; +import { DatasetTableSortField } from '../../../hooks'; interface FiltersCriteria { inactive: boolean; @@ -26,6 +31,7 @@ interface FiltersCriteria { integrations: string[]; namespaces: string[]; qualities: QualityIndicators[]; + types: string[]; query?: string; } @@ -37,13 +43,15 @@ export interface WithFilters { filters: FiltersCriteria; } +export type DictionaryType = Record; + export interface WithDataStreamStats { datasetUserPrivileges: DatasetUserPrivileges; dataStreamStats: DataStreamStatType[]; } export interface WithDegradedDocs { - degradedDocStats: DegradedDocsStat[]; + degradedDocStats: DictionaryType; } export interface WithNonAggregatableDatasets { @@ -59,9 +67,9 @@ export interface WithIntegrations { integrations: Integration[]; } -export type DefaultDatasetQualityControllerState = { type: string } & WithTableOptions & +export type DefaultDatasetQualityControllerState = WithTableOptions & WithDataStreamStats & - Partial & + WithDegradedDocs & WithDatasets & WithFilters & WithNonAggregatableDatasets & @@ -71,19 +79,19 @@ type DefaultDatasetQualityStateContext = DefaultDatasetQualityControllerState; export type DatasetQualityControllerTypeState = | { - value: 'datasets.fetching'; + value: 'stats.datasets.fetching'; context: DefaultDatasetQualityStateContext; } | { - value: 'datasets.loaded'; + value: 'stats.datasets.loaded'; context: DefaultDatasetQualityStateContext; } | { - value: 'datasets.loaded.idle'; + value: 'stats.degradedDocs.fetching'; context: DefaultDatasetQualityStateContext; } | { - value: 'degradedDocs.fetching'; + value: 'stats.nonAggregatableDatasets.fetching'; context: DefaultDatasetQualityStateContext; } | { @@ -135,6 +143,10 @@ export type DatasetQualityControllerEvent = type: 'UPDATE_QUERY'; query: string; } + | { + type: 'UPDATE_TYPES'; + types: DataStreamType[]; + } | DoneInvokeEvent | DoneInvokeEvent | DoneInvokeEvent diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts index 74dca94990190..c18f3d479ee95 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts @@ -427,7 +427,7 @@ export const createDatasetQualityDetailsControllerStateMachine = ({ const { startDate: start, endDate: end } = getDateISORange(context.timeRange); return dataStreamStatsClient.getNonAggregatableDatasets({ - type, + types: [type], start, end, dataStream: context.dataStream, @@ -479,9 +479,7 @@ export const createDatasetQualityDetailsControllerStateMachine = ({ }, loadDataStreamIntegration: (context) => { if ('dataStreamSettings' in context && context.dataStreamSettings?.integration) { - const { type } = indexNameToDataStreamParts(context.dataStream); return dataStreamDetailsClient.getDataStreamIntegration({ - type, integrationName: context.dataStreamSettings.integration, }); } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts new file mode 100644 index 0000000000000..70a861191ba9f --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DataStreamType } from '../../common/types'; + +export function flattenStats( + stats: Record +): Array { + return Object.entries(stats).flatMap(([type, dataStreams]) => + dataStreams.map((dataStream) => ({ ...dataStream, type: type as DataStreamType })) + ); +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts index b6ce00628dd51..6f2e46baacf8c 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts @@ -8,7 +8,8 @@ import { indexNameToDataStreamParts } from '../../common/utils'; import { Integration } from '../../common/data_streams_stats/integration'; import { generateDatasets } from './generate_datasets'; -import { DataStreamStatType } from '../../common/data_streams_stats/types'; +import { DataStreamStatType } from '../../common/data_streams_stats'; +import { DEFAULT_DICTIONARY_TYPE } from '../state_machines/dataset_quality_controller'; describe('generateDatasets', () => { const integrations: Integration[] = [ @@ -56,25 +57,28 @@ describe('generateDatasets', () => { }, ]; - const degradedDocs = [ - { - dataset: 'logs-system.application-default', - percentage: 0, - count: 0, - docsCount: 0, - quality: 'good' as const, - }, - { - dataset: 'logs-synth-default', - percentage: 11.320754716981131, - count: 6, - docsCount: 0, - quality: 'poor' as const, - }, - ]; + const degradedDocs = { + ...DEFAULT_DICTIONARY_TYPE, + logs: [ + { + dataset: 'logs-system.application-default', + percentage: 0, + count: 0, + docsCount: 0, + quality: 'good' as const, + }, + { + dataset: 'logs-synth-default', + percentage: 11.320754716981131, + count: 6, + docsCount: 0, + quality: 'poor' as const, + }, + ], + }; it('merges integrations information with dataStreamStats', () => { - const datasets = generateDatasets(dataStreamStats, undefined, integrations); + const datasets = generateDatasets(dataStreamStats, DEFAULT_DICTIONARY_TYPE, integrations); expect(datasets).toEqual([ { @@ -87,10 +91,10 @@ describe('generateDatasets', () => { rawName: dataStreamStats[0].name, integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { @@ -115,40 +119,42 @@ describe('generateDatasets', () => { expect(datasets).toEqual([ { - rawName: degradedDocs[0].dataset, - name: indexNameToDataStreamParts(degradedDocs[0].dataset).dataset, - type: indexNameToDataStreamParts(degradedDocs[0].dataset).type, + rawName: degradedDocs.logs[0].dataset, + name: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).dataset, + type: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).type, lastActivity: undefined, size: undefined, sizeBytes: undefined, userPrivileges: undefined, - namespace: indexNameToDataStreamParts(degradedDocs[0].dataset).namespace, + namespace: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).namespace, title: - integrations[0].datasets[indexNameToDataStreamParts(degradedDocs[0].dataset).dataset], + integrations[0].datasets[ + indexNameToDataStreamParts(degradedDocs.logs[0].dataset).dataset + ], integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { - rawName: degradedDocs[1].dataset, - name: indexNameToDataStreamParts(degradedDocs[1].dataset).dataset, - type: indexNameToDataStreamParts(degradedDocs[1].dataset).type, + rawName: degradedDocs.logs[1].dataset, + name: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).dataset, + type: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).type, lastActivity: undefined, size: undefined, sizeBytes: undefined, userPrivileges: undefined, - namespace: indexNameToDataStreamParts(degradedDocs[1].dataset).namespace, - title: indexNameToDataStreamParts(degradedDocs[1].dataset).dataset, + namespace: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).namespace, + title: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).dataset, integration: undefined, degradedDocs: { - percentage: degradedDocs[1].percentage, - count: degradedDocs[1].count, - docsCount: degradedDocs[1].docsCount, - quality: degradedDocs[1].quality, + percentage: degradedDocs.logs[1].percentage, + count: degradedDocs.logs[1].count, + docsCount: degradedDocs.logs[1].docsCount, + quality: degradedDocs.logs[1].quality, }, }, ]); @@ -168,10 +174,10 @@ describe('generateDatasets', () => { rawName: dataStreamStats[0].name, integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { @@ -182,10 +188,10 @@ describe('generateDatasets', () => { type: indexNameToDataStreamParts(dataStreamStats[1].name).type, rawName: dataStreamStats[1].name, degradedDocs: { - percentage: degradedDocs[1].percentage, - count: degradedDocs[1].count, - docsCount: degradedDocs[1].docsCount, - quality: degradedDocs[1].quality, + percentage: degradedDocs.logs[1].percentage, + count: degradedDocs.logs[1].count, + docsCount: degradedDocs.logs[1].docsCount, + quality: degradedDocs.logs[1].quality, }, }, ]); @@ -205,7 +211,7 @@ describe('generateDatasets', () => { }, }; - const datasets = generateDatasets([nonDefaultDataset], undefined, integrations); + const datasets = generateDatasets([nonDefaultDataset], DEFAULT_DICTIONARY_TYPE, integrations); expect(datasets).toEqual([ { @@ -225,8 +231,4 @@ describe('generateDatasets', () => { }, ]); }); - - it('returns an empty array if no valid object is provided', () => { - expect(generateDatasets(undefined, undefined, integrations)).toEqual([]); - }); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts index ca6dc793d35e5..fb479198bbac3 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts @@ -10,10 +10,12 @@ import { mapPercentageToQuality } from '../../common/utils'; import { Integration } from '../../common/data_streams_stats/integration'; import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat'; import { DegradedDocsStat } from '../../common/data_streams_stats/malformed_docs_stat'; +import { DictionaryType } from '../state_machines/dataset_quality_controller/src/types'; +import { flattenStats } from './flatten_stats'; export function generateDatasets( dataStreamStats: DataStreamStatType[] = [], - degradedDocStats: DegradedDocsStat[] = [], + degradedDocStats: DictionaryType, integrations: Integration[] ): DataStreamStat[] { if (!dataStreamStats.length && !integrations.length) { @@ -48,8 +50,10 @@ export function generateDatasets( { datasetIntegrationMap: {}, integrationsMap: {} } ); + const degradedDocs = flattenStats(degradedDocStats); + if (!dataStreamStats.length) { - return degradedDocStats.map((degradedDocStat) => + return degradedDocs.map((degradedDocStat) => DataStreamStat.fromDegradedDocStat({ degradedDocStat, datasetIntegrationMap }) ); } @@ -62,8 +66,8 @@ export function generateDatasets( docsCount: DegradedDocsStat['docsCount']; quality: DegradedDocsStat['quality']; } - > = degradedDocStats.reduce( - (degradedMapAcc, { dataset, percentage, count, docsCount, quality }) => + > = degradedDocs.reduce( + (degradedMapAcc, { dataset, percentage, count, docsCount }) => Object.assign(degradedMapAcc, { [dataset]: { percentage, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts index ae28384e7a160..907c0c0fdc05c 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts @@ -40,13 +40,13 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const result = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: true, }); expect(dataStreamService.getMatchingDataStreams).toHaveBeenCalledWith( expect.anything(), - 'logs-*nginx*' + 'logs-nginx-*' ); expect(result.datasetUserPrivileges.canMonitor).toBe(true); @@ -57,8 +57,8 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const results = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: true, }); expect(results.items.length).toBe(1); @@ -67,8 +67,8 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const results = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: false, }); expect(results.items.length).toBe(5); diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts index 346946d8bed5c..853a0cf208b42 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts @@ -6,27 +6,28 @@ */ import type { ElasticsearchClient } from '@kbn/core/server'; -import { DEFAULT_DATASET_TYPE } from '../../../../common/constants'; import { streamPartsToIndexPattern } from '../../../../common/utils'; import { DataStreamType } from '../../../../common/types'; import { dataStreamService, datasetQualityPrivileges } from '../../../services'; export async function getDataStreams(options: { esClient: ElasticsearchClient; - type?: DataStreamType; + types: DataStreamType[]; datasetQuery?: string; uncategorisedOnly: boolean; }) { - const { esClient, type = DEFAULT_DATASET_TYPE, datasetQuery, uncategorisedOnly } = options; + const { esClient, types, datasetQuery, uncategorisedOnly } = options; - const datasetName = streamPartsToIndexPattern({ - typePattern: type, - datasetPattern: datasetQuery ? `*${datasetQuery}*` : '*-*', - }); + const datasetNames = types.map((type) => + streamPartsToIndexPattern({ + typePattern: type, + datasetPattern: datasetQuery ? `${datasetQuery}` : '*-*', + }) + ); const datasetUserPrivileges = await datasetQualityPrivileges.getDatasetPrivileges( esClient, - datasetName + datasetNames.join(',') ); if (!datasetUserPrivileges.canMonitor) { @@ -36,7 +37,10 @@ export async function getDataStreams(options: { }; } - const allDataStreams = await dataStreamService.getMatchingDataStreams(esClient, datasetName); + const allDataStreams = await dataStreamService.getMatchingDataStreams( + esClient, + datasetNames.join(',') + ); const filteredDataStreams = uncategorisedOnly ? allDataStreams.filter((stream) => { diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts index b59999d0c3c2e..6137bc5426f86 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts @@ -8,28 +8,29 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { rangeQuery } from '@kbn/observability-plugin/server/utils/queries'; import { extractIndexNameFromBackingIndex } from '../../../common/utils'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; import { _IGNORED } from '../../../common/es_fields'; import { DataStreamType } from '../../../common/types'; import { createDatasetQualityESClient } from '../../utils'; export async function getNonAggregatableDataStreams({ esClient, - type = DEFAULT_DATASET_TYPE, + types, start, end, dataStream, }: { esClient: ElasticsearchClient; - type?: DataStreamType; + types: DataStreamType[]; start: number; end: number; dataStream?: string; }) { const datasetQualityESClient = createDatasetQualityESClient(esClient); + const dataStreamTypes = types.map((type) => `${type}-*-*`).join(','); + const response = await datasetQualityESClient.fieldCaps({ - index: dataStream ?? `${type}-*-*`, + index: dataStream ?? dataStreamTypes, fields: [_IGNORED], index_filter: { ...rangeQuery(start, end)[0], diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts index 9862b11cf16e0..54a229cb790e7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts @@ -16,7 +16,7 @@ import { DegradedFieldResponse, DatasetUserPrivileges, } from '../../../common/api_types'; -import { rangeRt, typeRt } from '../../types/default_api_types'; +import { rangeRt, typeRt, typesRt } from '../../types/default_api_types'; import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route'; import { datasetQualityPrivileges } from '../../services'; import { getDataStreamDetails, getDataStreamSettings } from './get_data_stream_details'; @@ -30,7 +30,7 @@ const statsRoute = createDatasetQualityServerRoute({ endpoint: 'GET /internal/dataset_quality/data_streams/stats', params: t.type({ query: t.intersection([ - typeRt, + t.type({ types: typesRt }), t.partial({ datasetQuery: t.string, }), @@ -59,6 +59,7 @@ const statsRoute = createDatasetQualityServerRoute({ const privilegedDataStreams = items.filter((stream) => { return stream.userPrivileges.canMonitor; }); + const dataStreamsStats = await getDataStreamsStats({ esClient, dataStreams: privilegedDataStreams.map((stream) => stream.name), @@ -116,7 +117,7 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({ params: t.type({ query: t.intersection([ rangeRt, - typeRt, + t.type({ types: typesRt }), t.partial({ dataStream: t.string, }), @@ -131,11 +132,36 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({ const esClient = coreContext.elasticsearch.client.asCurrentUser; + return await getNonAggregatableDataStreams({ + esClient, + ...params.query, + }); + }, +}); + +const nonAggregatableDatasetRoute = createDatasetQualityServerRoute({ + endpoint: 'GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable', + params: t.type({ + path: t.type({ + dataStream: t.string, + }), + query: t.intersection([rangeRt, typeRt]), + }), + options: { + tags: [], + }, + async handler(resources): Promise { + const { context, params } = resources; + const coreContext = await context.core; + + const esClient = coreContext.elasticsearch.client.asCurrentUser; + await datasetQualityPrivileges.throwIfCannotReadDataset(esClient, params.query.type); return await getNonAggregatableDataStreams({ esClient, ...params.query, + types: [params.query.type], }); }, }); @@ -230,6 +256,7 @@ export const dataStreamsRouteRepository = { ...statsRoute, ...degradedDocsRoute, ...nonAggregatableDatasetsRoute, + ...nonAggregatableDatasetRoute, ...degradedFieldsRoute, ...dataStreamDetailsRoute, ...dataStreamSettingsRoute, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts index 208ed7e70ab32..10e89db800a20 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts @@ -9,16 +9,13 @@ import { Logger } from '@kbn/core/server'; import { PackageClient } from '@kbn/fleet-plugin/server'; import { PackageNotFoundError } from '@kbn/fleet-plugin/server/errors'; import { PackageListItem, RegistryDataStream } from '@kbn/fleet-plugin/common'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; -import { DataStreamType } from '../../../common/types'; import { IntegrationType } from '../../../common/api_types'; export async function getIntegrations(options: { packageClient: PackageClient; logger: Logger; - type?: DataStreamType; }): Promise { - const { packageClient, logger, type = DEFAULT_DATASET_TYPE } = options; + const { packageClient, logger } = options; const packages = await packageClient.getPackages(); const installedPackages = packages.filter((p) => p.status === 'installed'); @@ -29,7 +26,7 @@ export async function getIntegrations(options: { title: p.title, version: p.version, icons: p.icons, - datasets: await getDatasets({ packageClient, logger, pkg: p, type }), + datasets: await getDatasets({ packageClient, logger, pkg: p }), })) ); @@ -40,9 +37,8 @@ const getDatasets = async (options: { packageClient: PackageClient; logger: Logger; pkg: PackageListItem; - type: DataStreamType; }) => { - const { packageClient, logger, pkg, type } = options; + const { packageClient, logger, pkg } = options; return ( (await fetchDatasets({ @@ -50,7 +46,6 @@ const getDatasets = async (options: { logger, name: pkg.name, version: pkg.version, - type, })) ?? getDatasetsReadableName(pkg.data_streams ?? []) ); }; @@ -60,16 +55,13 @@ const fetchDatasets = async (options: { logger: Logger; name: string; version: string; - type: DataStreamType; }) => { try { - const { packageClient, name, version, type } = options; + const { packageClient, name, version } = options; const pkg = await packageClient.getPackage(name, version); - return getDatasetsReadableName( - (pkg.packageInfo.data_streams ?? []).filter((ds) => ds.type === type) - ); + return getDatasetsReadableName(pkg.packageInfo.data_streams ?? []); } catch (error) { // Custom integration if (error instanceof PackageNotFoundError) { diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts index 1a21d7e1a14c4..dfeb2f3329bae 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts @@ -7,28 +7,24 @@ import * as t from 'io-ts'; import { IntegrationType, IntegrationDashboardsResponse } from '../../../common/api_types'; -import { typeRt } from '../../types/default_api_types'; import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route'; import { getIntegrations } from './get_integrations'; import { getIntegrationDashboards } from './get_integration_dashboards'; const integrationsRoute = createDatasetQualityServerRoute({ endpoint: 'GET /internal/dataset_quality/integrations', - params: t.type({ - query: typeRt, - }), options: { tags: [], }, async handler(resources): Promise<{ integrations: IntegrationType[]; }> { - const { params, plugins, logger } = resources; + const { plugins, logger } = resources; const fleetPluginStart = await plugins.fleet.start(); const packageClient = fleetPluginStart.packageService.asInternalUser; - const integrations = await getIntegrations({ packageClient, logger, ...params.query }); + const integrations = await getIntegrations({ packageClient, logger }); return { integrations }; }, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts b/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts index 91eb8698dfcac..c2b746e655280 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts @@ -7,12 +7,24 @@ import { isoToEpochRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; -import { dataStreamTypesRt } from '../../common/types'; +import { DataStreamType, dataStreamTypesRt } from '../../common/types'; -export const typeRt = t.partial({ +export const typeRt = t.type({ type: dataStreamTypesRt, }); +export const typesRt = new t.Type( + 'typesRt', + (input: unknown): input is DataStreamType[] => + (typeof input === 'string' && input.split(',').every((value) => dataStreamTypesRt.is(value))) || + (Array.isArray(input) && input.every((value) => dataStreamTypesRt.is(value))), + (input, context) => + typeof input === 'string' && input.split(',').every((value) => dataStreamTypesRt.is(value)) + ? t.success(input.split(',') as DataStreamType[]) + : t.failure(input, context), + t.identity +); + export const rangeRt = t.type({ start: isoToEpochRt, end: isoToEpochRt, diff --git a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json index 04d5362bb9861..8bec2d8cb1a63 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json +++ b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json @@ -55,7 +55,8 @@ "@kbn/server-route-repository-utils", "@kbn/core-analytics-browser", "@kbn/core-lifecycle-browser", - "@kbn/core-notifications-browser" + "@kbn/core-notifications-browser", + "@kbn/rison" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 86e3e5702baad..f0ef033d63236 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -14608,7 +14608,6 @@ "xpack.dataQuality.Initializing": "Page Initialisation de la qualité de l'ensemble de données", "xpack.dataQuality.name": "Qualité de l’ensemble de données", "xpack.datasetQuality.actionsColumnName": "Actions", - "xpack.datasetQuality.appDescription": "Surveillez la qualité du jeu de données pour les flux de données {logsPattern} suivant le {dsNamingSchemeLink}.", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "Schéma de dénomination du flux de données", "xpack.datasetQuality.appTitle": "Qualité de l’ensemble de données", "xpack.datasetQuality.betaBadgeDescription": "Cette fonctionnalité est actuellement en version bêta. Nous aimerions beaucoup savoir si vous avez des commentaires ou si vous rencontrez des bugs. Veuillez ouvrir un dossier d'assistance et/ou consulter notre forum de discussion.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0ab34991b457d..b3be85aaa7bd1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14597,7 +14597,6 @@ "xpack.dataQuality.Initializing": "データセット品質ページを初期化中", "xpack.dataQuality.name": "データセット品質", "xpack.datasetQuality.actionsColumnName": "アクション", - "xpack.datasetQuality.appDescription": "{dsNamingSchemeLink}に従う{logsPattern}データストリームのデータセット品質を監視します。", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "データストリーム命名スキーム", "xpack.datasetQuality.appTitle": "データセット品質", "xpack.datasetQuality.betaBadgeDescription": "現在、この機能はベータです。バグが発生した場合やフィードバックがある場合は、お問い合わせください。サポート問題をオープンするか、ディスカッションフォーラムをご覧ください。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9698931c132f7..6ffabdf583e73 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -14620,7 +14620,6 @@ "xpack.dataQuality.Initializing": "正在初始化“数据集质量”页面", "xpack.dataQuality.name": "数据集质量", "xpack.datasetQuality.actionsColumnName": "操作", - "xpack.datasetQuality.appDescription": "监测跟随 {dsNamingSchemeLink} 的 {logsPattern} 数据流的数据集质量。", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "数据流命名方案", "xpack.datasetQuality.appTitle": "数据集质量", "xpack.datasetQuality.betaBadgeDescription": "此功能当前为公测版。如果遇到任何错误或有任何反馈,我们乐于倾听您的意见。请报告支持问题和/或访问我们的讨论论坛。", diff --git a/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts index b01dc1f2375aa..25a7f419f2746 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts @@ -22,8 +22,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { endpoint: 'GET /internal/dataset_quality/data_streams/stats', params: { query: { - type: 'logs', - datasetQuery: '-', + types: ['logs'], }, }, }); diff --git a/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts index 13011410a0317..2176dbd1fa95d 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts @@ -39,11 +39,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { return await datasetQualityApiClient[user]({ endpoint: 'GET /internal/dataset_quality/integrations', - params: { - query: { - type: 'logs', - }, - }, }); } @@ -53,12 +48,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { await Promise.all(integrationPackages.map((pkg) => installPackage({ supertest, pkg }))); }); - it('returns only log based integrations and its datasets map', async () => { + it('returns all installed integrations and its datasets map', async () => { const resp = await callApiAs(); expect(resp.body.integrations.map((integration) => integration.name)).to.eql([ 'apm', 'endpoint', + 'synthetics', 'system', ]); From 0a8d6a0afc8b9cf8994a216f0e913310c0bba5ce Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Tue, 27 Aug 2024 08:43:47 -0700 Subject: [PATCH 38/38] [UII] Add retries to starting Kibana for jest preconfiguration integration tests (#191318) ## Summary Resolves #172759 Resolves #172760 Resolves #172761 Add retries to starting Kibana for this test suite to hopefully mitigate future flakiness. ### Checklist - ~~[Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed~~ Doesn't seem like I can run Jest integration tests here. --- .../cloud_preconfiguration.test.ts | 104 ++++++++++-------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts index 5ffe6b643f77d..97bd1145fa5ca 100644 --- a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts @@ -49,56 +49,74 @@ describe('Fleet cloud preconfiguration', () => { esServer = await startES(); const startOrRestartKibana = async (kbnConfig: any = defaultKbnConfig) => { - if (kbnServer) { - await kbnServer.stop(); - } - - const root = createRootWithCorePlugins( - { - xpack: { - ...kbnConfig.xpack, - fleet: { - ...kbnConfig.xpack.fleet, - registryUrl, + const maxTries = 3; + let currentTry = 0; + + const startOrRestart = async () => { + if (kbnServer) { + await kbnServer.stop(); + } + + const root = createRootWithCorePlugins( + { + xpack: { + ...kbnConfig.xpack, + fleet: { + ...kbnConfig.xpack.fleet, + registryUrl, + }, }, - }, - logging: { - appenders: { - file: { - type: 'file', - fileName: logFilePath, - layout: { - type: 'json', + logging: { + appenders: { + file: { + type: 'file', + fileName: logFilePath, + layout: { + type: 'json', + }, }, }, + loggers: [ + { + name: 'root', + appenders: ['file'], + }, + { + name: 'plugins.fleet', + level: 'all', + }, + ], }, - loggers: [ - { - name: 'root', - appenders: ['file'], - }, - { - name: 'plugins.fleet', - level: 'all', - }, - ], }, - }, - { oss: false } - ); - - await root.preboot(); - const coreSetup = await root.setup(); - const coreStart = await root.start(); - - kbnServer = { - root, - coreSetup, - coreStart, - stop: async () => await root.shutdown(), + { oss: false } + ); + + await root.preboot(); + const coreSetup = await root.setup(); + const coreStart = await root.start(); + + kbnServer = { + root, + coreSetup, + coreStart, + stop: async () => await root.shutdown(), + }; + + await waitForFleetSetup(kbnServer.root); }; - await waitForFleetSetup(kbnServer.root); + + try { + currentTry++; + await startOrRestart(); + } catch (e) { + if (currentTry < maxTries) { + await startOrRestart(); + } else { + throw e; + } + } }; + await startOrRestartKibana(); return {