diff --git a/.eslintrc.js b/.eslintrc.js index 5ee75d186eb24..f3d3e700fec30 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -226,10 +226,6 @@ const RESTRICTED_IMPORTS = [ name: 'react-use', message: 'Please use react-use/lib/{method} instead.', }, - { - name: '@kbn/io-ts-utils', - message: `Import directly from @kbn/io-ts-utils/{method} submodules`, - }, ]; module.exports = { diff --git a/package.json b/package.json index 4e7044b458a44..0ff755d675911 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "**/istanbul-lib-coverage": "^3.2.0", "**/json-schema": "^0.4.0", "**/minimist": "^1.2.5", - "**/node-forge": "^1.1.0", + "**/node-forge": "^1.2.1", "**/pdfkit/crypto-js": "4.0.0", "**/react-syntax-highlighter": "^15.3.1", "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", @@ -302,7 +302,7 @@ "mustache": "^2.3.2", "nock": "12.0.3", "node-fetch": "^2.6.1", - "node-forge": "^1.1.0", + "node-forge": "^1.2.1", "nodemailer": "^6.6.2", "normalize-path": "^3.0.0", "object-hash": "^1.3.1", @@ -578,6 +578,7 @@ "@types/kbn__i18n": "link:bazel-bin/packages/kbn-i18n/npm_module_types", "@types/kbn__i18n-react": "link:bazel-bin/packages/kbn-i18n-react/npm_module_types", "@types/kbn__interpreter": "link:bazel-bin/packages/kbn-interpreter/npm_module_types", + "@types/kbn__io-ts-utils": "link:bazel-bin/packages/kbn-io-ts-utils/npm_module_types", "@types/kbn__mapbox-gl": "link:bazel-bin/packages/kbn-mapbox-gl/npm_module_types", "@types/kbn__monaco": "link:bazel-bin/packages/kbn-monaco/npm_module_types", "@types/kbn__optimizer": "link:bazel-bin/packages/kbn-optimizer/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index be4d1087bc21a..936091a3b85c2 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -97,6 +97,7 @@ filegroup( "//packages/kbn-i18n:build_types", "//packages/kbn-i18n-react:build_types", "//packages/kbn-interpreter:build_types", + "//packages/kbn-io-ts-utils:build_types", "//packages/kbn-mapbox-gl:build_types", "//packages/kbn-monaco:build_types", "//packages/kbn-optimizer:build_types", diff --git a/packages/kbn-io-ts-utils/BUILD.bazel b/packages/kbn-io-ts-utils/BUILD.bazel index dd81e8318e9d9..5ecfc0acc55e8 100644 --- a/packages/kbn-io-ts-utils/BUILD.bazel +++ b/packages/kbn-io-ts-utils/BUILD.bazel @@ -1,9 +1,10 @@ -load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") -load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") -load("//src/dev/bazel:index.bzl", "jsts_transpiler") +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") PKG_BASE_NAME = "kbn-io-ts-utils" PKG_REQUIRE_NAME = "@kbn/io-ts-utils" +TYPES_PKG_REQUIRE_NAME = "@types/kbn__io-ts-utils" SOURCE_FILES = glob( [ @@ -23,17 +24,6 @@ filegroup( NPM_MODULE_EXTRA_FILES = [ "package.json", - "deep_exact_rt/package.json", - "iso_to_epoch_rt/package.json", - "json_rt/package.json", - "merge_rt/package.json", - "non_empty_string_rt/package.json", - "parseable_types/package.json", - "props_to_schema/package.json", - "strict_keys_rt/package.json", - "to_boolean_rt/package.json", - "to_json_schema/package.json", - "to_number_rt/package.json", ] RUNTIME_DEPS = [ @@ -86,7 +76,7 @@ ts_project( js_library( name = PKG_BASE_NAME, srcs = NPM_MODULE_EXTRA_FILES, - deps = RUNTIME_DEPS + [":target_node", ":tsc_types"], + deps = RUNTIME_DEPS + [":target_node"], package_name = PKG_REQUIRE_NAME, visibility = ["//visibility:public"], ) @@ -105,3 +95,20 @@ filegroup( ], visibility = ["//visibility:public"], ) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = TYPES_PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [ + ":npm_module_types", + ], + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-io-ts-utils/deep_exact_rt/package.json b/packages/kbn-io-ts-utils/deep_exact_rt/package.json deleted file mode 100644 index b42591a2e82d0..0000000000000 --- a/packages/kbn-io-ts-utils/deep_exact_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/deep_exact_rt", - "types": "../target_types/deep_exact_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/iso_to_epoch_rt/package.json b/packages/kbn-io-ts-utils/iso_to_epoch_rt/package.json deleted file mode 100644 index e96c50b9fbf4e..0000000000000 --- a/packages/kbn-io-ts-utils/iso_to_epoch_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/iso_to_epoch_rt", - "types": "../target_types/iso_to_epoch_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/json_rt/package.json b/packages/kbn-io-ts-utils/json_rt/package.json deleted file mode 100644 index f896827cf99a4..0000000000000 --- a/packages/kbn-io-ts-utils/json_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/json_rt", - "types": "../target_types/json_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/merge_rt/package.json b/packages/kbn-io-ts-utils/merge_rt/package.json deleted file mode 100644 index f7773688068e0..0000000000000 --- a/packages/kbn-io-ts-utils/merge_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/merge_rt", - "types": "../target_types/merge_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/non_empty_string_rt/package.json b/packages/kbn-io-ts-utils/non_empty_string_rt/package.json deleted file mode 100644 index 6348f6d728059..0000000000000 --- a/packages/kbn-io-ts-utils/non_empty_string_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/non_empty_string_rt", - "types": "../target_types/non_empty_string_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/package.json b/packages/kbn-io-ts-utils/package.json index fb1179b06bf45..2dc3532e05d96 100644 --- a/packages/kbn-io-ts-utils/package.json +++ b/packages/kbn-io-ts-utils/package.json @@ -1,7 +1,6 @@ { "name": "@kbn/io-ts-utils", "main": "./target_node/index.js", - "types": "./target_types/index.d.ts", "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0", "private": true diff --git a/packages/kbn-io-ts-utils/parseable_types/package.json b/packages/kbn-io-ts-utils/parseable_types/package.json deleted file mode 100644 index 6dab2a5ee156e..0000000000000 --- a/packages/kbn-io-ts-utils/parseable_types/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/parseable_types", - "types": "../target_types/parseable_types" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/props_to_schema/package.json b/packages/kbn-io-ts-utils/props_to_schema/package.json deleted file mode 100644 index 478de84d17f81..0000000000000 --- a/packages/kbn-io-ts-utils/props_to_schema/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/props_to_schema", - "types": "../target_types/props_to_schema" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/src/index.ts b/packages/kbn-io-ts-utils/src/index.ts index 88cfc063f738a..a01e6c41d79d6 100644 --- a/packages/kbn-io-ts-utils/src/index.ts +++ b/packages/kbn-io-ts-utils/src/index.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +export type { NonEmptyStringBrand } from './non_empty_string_rt'; + export { deepExactRt } from './deep_exact_rt'; export { jsonRt } from './json_rt'; export { mergeRt } from './merge_rt'; diff --git a/packages/kbn-io-ts-utils/strict_keys_rt/package.json b/packages/kbn-io-ts-utils/strict_keys_rt/package.json deleted file mode 100644 index 68823d97a5d00..0000000000000 --- a/packages/kbn-io-ts-utils/strict_keys_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/strict_keys_rt", - "types": "../target_types/strict_keys_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/to_boolean_rt/package.json b/packages/kbn-io-ts-utils/to_boolean_rt/package.json deleted file mode 100644 index 5e801a6529153..0000000000000 --- a/packages/kbn-io-ts-utils/to_boolean_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/to_boolean_rt", - "types": "../target_types/to_boolean_rt" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/to_json_schema/package.json b/packages/kbn-io-ts-utils/to_json_schema/package.json deleted file mode 100644 index 366f3243b1156..0000000000000 --- a/packages/kbn-io-ts-utils/to_json_schema/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/to_json_schema", - "types": "../target_types/to_json_schema" -} \ No newline at end of file diff --git a/packages/kbn-io-ts-utils/to_number_rt/package.json b/packages/kbn-io-ts-utils/to_number_rt/package.json deleted file mode 100644 index f5da955cb9775..0000000000000 --- a/packages/kbn-io-ts-utils/to_number_rt/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "../target_node/to_number_rt", - "types": "../target_types/to_number_rt" -} \ No newline at end of file diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index c6edd30549a76..e49b47c712780 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -47,6 +47,7 @@ const ALERT_RULE_CREATED_AT = `${ALERT_RULE_NAMESPACE}.created_at` as const; const ALERT_RULE_CREATED_BY = `${ALERT_RULE_NAMESPACE}.created_by` as const; const ALERT_RULE_DESCRIPTION = `${ALERT_RULE_NAMESPACE}.description` as const; const ALERT_RULE_ENABLED = `${ALERT_RULE_NAMESPACE}.enabled` as const; +const ALERT_RULE_EXECUTION_UUID = `${ALERT_RULE_NAMESPACE}.execution.uuid` as const; const ALERT_RULE_FROM = `${ALERT_RULE_NAMESPACE}.from` as const; const ALERT_RULE_INTERVAL = `${ALERT_RULE_NAMESPACE}.interval` as const; const ALERT_RULE_LICENSE = `${ALERT_RULE_NAMESPACE}.license` as const; @@ -103,6 +104,7 @@ const fields = { ALERT_RULE_CREATED_BY, ALERT_RULE_DESCRIPTION, ALERT_RULE_ENABLED, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_FROM, ALERT_RULE_INTERVAL, ALERT_RULE_LICENSE, @@ -156,6 +158,7 @@ export { ALERT_RULE_CREATED_BY, ALERT_RULE_DESCRIPTION, ALERT_RULE_ENABLED, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_FROM, ALERT_RULE_INTERVAL, ALERT_RULE_LICENSE, diff --git a/packages/kbn-server-route-repository/BUILD.bazel b/packages/kbn-server-route-repository/BUILD.bazel index 103f15bbf5d6a..a0e1cf41dcf8f 100644 --- a/packages/kbn-server-route-repository/BUILD.bazel +++ b/packages/kbn-server-route-repository/BUILD.bazel @@ -38,7 +38,7 @@ RUNTIME_DEPS = [ TYPES_DEPS = [ "//packages/kbn-config-schema:npm_module_types", - "//packages/kbn-io-ts-utils", + "//packages/kbn-io-ts-utils:npm_module_types", "@npm//@hapi/boom", "@npm//fp-ts", "@npm//utility-types", diff --git a/packages/kbn-server-route-repository/src/decode_request_params.test.ts b/packages/kbn-server-route-repository/src/decode_request_params.test.ts index a5c1a2b49eb19..96035bc3e0011 100644 --- a/packages/kbn-server-route-repository/src/decode_request_params.test.ts +++ b/packages/kbn-server-route-repository/src/decode_request_params.test.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; +import { jsonRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { decodeRequestParams } from './decode_request_params'; diff --git a/packages/kbn-server-route-repository/src/decode_request_params.ts b/packages/kbn-server-route-repository/src/decode_request_params.ts index 4df6fa3333c50..00492d69b8ac5 100644 --- a/packages/kbn-server-route-repository/src/decode_request_params.ts +++ b/packages/kbn-server-route-repository/src/decode_request_params.ts @@ -10,7 +10,7 @@ import { omitBy, isPlainObject, isEmpty } from 'lodash'; import { isLeft } from 'fp-ts/lib/Either'; import { PathReporter } from 'io-ts/lib/PathReporter'; import Boom from '@hapi/boom'; -import { strictKeysRt } from '@kbn/io-ts-utils/strict_keys_rt'; +import { strictKeysRt } from '@kbn/io-ts-utils'; import { RouteParamsRT } from './typings'; interface KibanaRequestParams { diff --git a/packages/kbn-typed-react-router-config/BUILD.bazel b/packages/kbn-typed-react-router-config/BUILD.bazel index d759948a6c576..6f4e53e58fff7 100644 --- a/packages/kbn-typed-react-router-config/BUILD.bazel +++ b/packages/kbn-typed-react-router-config/BUILD.bazel @@ -37,7 +37,7 @@ RUNTIME_DEPS = [ ] TYPES_DEPS = [ - "//packages/kbn-io-ts-utils", + "//packages/kbn-io-ts-utils:npm_module_types", "@npm//query-string", "@npm//utility-types", "@npm//@types/jest", diff --git a/packages/kbn-typed-react-router-config/src/create_router.test.tsx b/packages/kbn-typed-react-router-config/src/create_router.test.tsx index ac337f8bb5b87..d29079f37ec12 100644 --- a/packages/kbn-typed-react-router-config/src/create_router.test.tsx +++ b/packages/kbn-typed-react-router-config/src/create_router.test.tsx @@ -7,19 +7,16 @@ */ import React from 'react'; import * as t from 'io-ts'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { createRouter } from './create_router'; import { createMemoryHistory } from 'history'; -import { route } from './route'; describe('createRouter', () => { - const routes = route([ - { - path: '/', + const routes = { + '/': { element: <>, - children: [ - { - path: '/', + children: { + '/': { element: <>, params: t.type({ query: t.type({ @@ -32,31 +29,27 @@ describe('createRouter', () => { rangeFrom: 'now-30m', }, }, - children: [ - { - path: '/services/{serviceName}/errors', + children: { + '/services/{serviceName}/errors': { element: <>, params: t.type({ path: t.type({ serviceName: t.string, }), }), - children: [ - { - path: '/services/{serviceName}/errors/{groupId}', + children: { + '/services/{serviceName}/errors/{groupId}': { element: <>, params: t.type({ path: t.type({ groupId: t.string }), }), }, - { - path: '/services/{serviceName}/errors', + '/services/{serviceName}/errors': { element: <>, }, - ], + }, }, - { - path: '/services', + '/services': { element: <>, params: t.type({ query: t.type({ @@ -64,13 +57,11 @@ describe('createRouter', () => { }), }), }, - { - path: '/services/{serviceName}', + '/services/{serviceName}': { element: <>, - children: [ - { + children: { + '/services/{serviceName}': { element: <>, - path: '/services/{serviceName}', params: t.type({ path: t.type({ serviceName: t.string, @@ -81,10 +72,9 @@ describe('createRouter', () => { }), }), }, - ], + }, }, - { - path: '/traces', + '/traces': { element: <>, params: t.type({ query: t.type({ @@ -93,8 +83,7 @@ describe('createRouter', () => { }), }), }, - { - path: '/service-map', + '/service-map': { element: <>, params: t.type({ query: t.type({ @@ -102,11 +91,11 @@ describe('createRouter', () => { }), }), }, - ], + }, }, - ], + }, }, - ] as const); + }; let history = createMemoryHistory(); const router = createRouter(routes); diff --git a/packages/kbn-typed-react-router-config/src/create_router.ts b/packages/kbn-typed-react-router-config/src/create_router.ts index 89ff4fc6b0c6c..494540005224a 100644 --- a/packages/kbn-typed-react-router-config/src/create_router.ts +++ b/packages/kbn-typed-react-router-config/src/create_router.ts @@ -15,27 +15,29 @@ import { } from 'react-router-config'; import qs from 'query-string'; import { findLastIndex, merge, compact } from 'lodash'; -import { mergeRt } from '@kbn/io-ts-utils/merge_rt'; -import { deepExactRt } from '@kbn/io-ts-utils/deep_exact_rt'; -import { FlattenRoutesOf, Route, Router } from './types'; +import { mergeRt, deepExactRt } from '@kbn/io-ts-utils'; +import { FlattenRoutesOf, Route, RouteWithPath, Router, RouteMap } from './types'; function toReactRouterPath(path: string) { return path.replace(/(?:{([^\/]+)})/g, ':$1'); } -export function createRouter(routes: TRoutes): Router { +export function createRouter(routes: TRoutes): Router { const routesByReactRouterConfig = new Map(); const reactRouterConfigsByRoute = new Map(); - const reactRouterConfigs = routes.map((route) => toReactRouterConfigRoute(route)); + const reactRouterConfigs = Object.entries(routes).map(([path, route]) => + toReactRouterConfigRoute({ ...route, path }) + ); - function toReactRouterConfigRoute(route: Route): ReactRouterConfig { + function toReactRouterConfigRoute(route: RouteWithPath): ReactRouterConfig { const reactRouterConfig: ReactRouterConfig = { component: () => route.element, routes: - (route.children as Route[] | undefined)?.map((child) => toReactRouterConfigRoute(child)) ?? - [], - exact: !route.children?.length, + Object.entries((route.children as RouteMap | undefined) ?? {})?.map(([path, child]) => + toReactRouterConfigRoute({ ...child, path }) + ) ?? [], + exact: !route.children || Object.values(route.children).length === 0, path: toReactRouterPath(route.path), }; diff --git a/packages/kbn-typed-react-router-config/src/index.ts b/packages/kbn-typed-react-router-config/src/index.ts index b58c70998901c..9ba68aed7e3b2 100644 --- a/packages/kbn-typed-react-router-config/src/index.ts +++ b/packages/kbn-typed-react-router-config/src/index.ts @@ -8,10 +8,8 @@ export * from './create_router'; export * from './types'; export * from './outlet'; -export * from './route'; export * from './route_renderer'; export * from './router_provider'; -export * from './unconst'; export * from './use_current_route'; export * from './use_match_routes'; export * from './use_params'; diff --git a/packages/kbn-typed-react-router-config/src/route.ts b/packages/kbn-typed-react-router-config/src/route.ts deleted file mode 100644 index b9b228d1009e2..0000000000000 --- a/packages/kbn-typed-react-router-config/src/route.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { Route } from './types'; -import { Unconst, unconst } from './unconst'; - -export function route( - r: TRoute -): Unconst { - return unconst(r); -} diff --git a/packages/kbn-typed-react-router-config/src/router_provider.tsx b/packages/kbn-typed-react-router-config/src/router_provider.tsx index 657df9e9fc592..ef06964f230be 100644 --- a/packages/kbn-typed-react-router-config/src/router_provider.tsx +++ b/packages/kbn-typed-react-router-config/src/router_provider.tsx @@ -8,7 +8,7 @@ import { History } from 'history'; import React from 'react'; import { Router as ReactRouter } from 'react-router-dom'; -import { Route, Router } from './types'; +import { RouteMap, Router } from './types'; import { RouterContextProvider } from './use_router'; export function RouterProvider({ @@ -16,7 +16,7 @@ export function RouterProvider({ router, history, }: { - router: Router; + router: Router; history: History; children: React.ReactNode; }) { diff --git a/packages/kbn-typed-react-router-config/src/types/index.ts b/packages/kbn-typed-react-router-config/src/types/index.ts index 97b58ce5a700f..a5121ba0d72c9 100644 --- a/packages/kbn-typed-react-router-config/src/types/index.ts +++ b/packages/kbn-typed-react-router-config/src/types/index.ts @@ -9,17 +9,31 @@ import { Location } from 'history'; import * as t from 'io-ts'; import { ReactElement } from 'react'; -import { RequiredKeys, ValuesType } from 'utility-types'; -// import { unconst } from '../unconst'; +import { RequiredKeys, ValuesType, UnionToIntersection } from 'utility-types'; import { NormalizePath } from './utils'; -// type PathsOfRoute = -// | TRoute['path'] -// | (TRoute extends { children: Route[] } -// ? AppendPath | PathsOf -// : never); +export type PathsOf = string & + ValuesType<{ + [key in keyof TRouteMap]: + | key + | (TRouteMap[key] extends { children: RouteMap } + ? AppendPath | PathsOf + : never); + }>; -export type PathsOf = keyof MapRoutes & string; +export type RouteMap = Record; + +export interface Route { + element: ReactElement; + children?: RouteMap; + params?: t.Type; + defaults?: Record>; + pre?: ReactElement; +} + +export interface RouteWithPath extends Route { + path: string; +} export interface RouteMatch { route: TRoute; @@ -35,91 +49,55 @@ export interface RouteMatch { }; } -type ToRouteMatch = TRoutes extends [] - ? [] - : TRoutes extends [Route] +type ToRouteMatch = TRoutes extends [Route] ? [RouteMatch] - : TRoutes extends [Route, ...infer TTail] - ? TTail extends Route[] - ? [RouteMatch, ...ToRouteMatch] - : [] - : []; - -type UnwrapRouteMap = TRoute extends { - parents: Route[]; -} - ? ToRouteMatch<[...TRoute['parents'], Omit]> - : ToRouteMatch<[Omit]>; - -export type Match = MapRoutes extends { - [key in TPath]: Route; -} - ? UnwrapRouteMap[TPath]> - : []; - -interface PlainRoute { - path: string; - element: ReactElement; - children?: PlainRoute[]; - params?: t.Type; - defaults?: Record>; - pre?: ReactElement; -} - -interface ReadonlyPlainRoute { - readonly path: string; - readonly element: ReactElement; - readonly children?: readonly ReadonlyPlainRoute[]; - readonly params?: t.Type; - readonly defaults?: Record>; - pre?: ReactElement; -} + : TRoutes extends [Route, ...infer TNextRoutes] + ? [RouteMatch, ...(TNextRoutes extends Route[] ? ToRouteMatch : [])] + : TRoutes extends [] + ? [] + : never; -export type Route = PlainRoute | ReadonlyPlainRoute; +export type Match = MapRoutes[TPath]; -interface DefaultOutput { +export interface DefaultOutput { path: {}; query: {}; } -type OutputOfRouteMatch = TRouteMatch extends { - route: { params: t.Type }; +type OutputOfRoute = TRoute extends { + params: t.Type; } - ? t.OutputOf - : DefaultOutput; + ? t.OutputOf + : {}; -type OutputOfMatches = TRouteMatches extends [RouteMatch] - ? OutputOfRouteMatch - : TRouteMatches extends [RouteMatch, ...infer TNextRouteMatches] - ? OutputOfRouteMatch & - (TNextRouteMatches extends RouteMatch[] ? OutputOfMatches : DefaultOutput) - : TRouteMatches extends RouteMatch[] - ? OutputOfRouteMatch> - : DefaultOutput; +type OutputOfRoutes = TRoutes extends [Route] + ? OutputOfRoute + : TRoutes extends [Route, ...infer TNextRoutes] + ? OutputOfRoute & (TNextRoutes extends Route[] ? OutputOfRoutes : {}) + : {}; -export type OutputOf> = OutputOfMatches< +export type OutputOf> = OutputOfRoutes< Match > & DefaultOutput; -type TypeOfRouteMatch = TRouteMatch extends { - route: { params: t.Type }; +type TypeOfRoute = TRoute extends { + params: t.Type; } - ? t.TypeOf + ? t.TypeOf : {}; -type TypeOfMatches = TRouteMatches extends [RouteMatch] - ? TypeOfRouteMatch - : TRouteMatches extends [RouteMatch, ...infer TNextRouteMatches] - ? TypeOfRouteMatch & - (TNextRouteMatches extends RouteMatch[] ? TypeOfMatches : {}) +type TypeOfRoutes = TRoutes extends [Route] + ? TypeOfRoute + : TRoutes extends [Route, ...infer TNextRoutes] + ? TypeOfRoute & (TNextRoutes extends Route[] ? TypeOfRoutes : {}) : {}; export type TypeOf< - TRoutes extends Route[], + TRoutes extends RouteMap, TPath extends PathsOf, TWithDefaultOutput extends boolean = true -> = TypeOfMatches> & (TWithDefaultOutput extends true ? DefaultOutput : {}); +> = TypeOfRoutes> & (TWithDefaultOutput extends true ? DefaultOutput : {}); export type TypeAsArgs = keyof TObject extends never ? [] @@ -127,16 +105,18 @@ export type TypeAsArgs = keyof TObject extends never ? [TObject] | [] : [TObject]; -export type FlattenRoutesOf = Array< - Omit>, 'parents'> +export type FlattenRoutesOf = Array< + ValuesType<{ + [key in keyof MapRoutes]: ValuesType[key]>; + }> >; -export interface Router { +export interface Router { matchRoutes>( path: TPath, location: Location - ): Match; - matchRoutes(location: Location): Match>; + ): ToRouteMatch>; + matchRoutes(location: Location): ToRouteMatch>>; getParams>( path: TPath, location: Location @@ -179,11 +159,11 @@ type MaybeUnion, U extends Record> = [key in keyof U]: key extends keyof T ? T[key] | U[key] : U[key]; }; -type MapRoute = MaybeUnion< +type MapRoute = MaybeUnion< { - [key in TRoute['path']]: TRoute & { parents: TParents }; + [key in TRoute['path']]: [...TParents, TRoute]; }, - TRoute extends { children: Route[] } + TRoute extends { children: RouteMap } ? MaybeUnion< MapRoutes, { @@ -195,107 +175,41 @@ type MapRoute = MaybeUnion< : {} >; -type MapRoutes = TRoutes extends [Route] - ? MapRoute - : TRoutes extends [Route, Route] - ? MapRoute & MapRoute - : TRoutes extends [Route, Route, Route] - ? MapRoute & MapRoute & MapRoute - : TRoutes extends [Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : TRoutes extends [Route, Route, Route, Route, Route, Route, Route, Route, Route, Route, Route] - ? MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute & - MapRoute - : {}; +type FromRouteMap< + TRouteMap extends RouteMap, + TParents extends RouteWithPath[] = [] +> = UnionToIntersection< + ValuesType<{ + [key in keyof TRouteMap]: MapRoute; + }> +>; + +type MapRoutes = FromRouteMap< + TRouteMap, + TParents +> extends Record + ? FromRouteMap + : never; // const element = null as any; -// const routes = unconst([ -// { -// path: '/link-to/transaction/{transactionId}', +// const routes = { +// '/link-to/transaction/{transactionId}': { // element, // }, -// { -// path: '/link-to/trace/{traceId}', +// '/link-to/trace/{traceId}': { // element, // }, -// { -// path: '/', +// '/': { // element, -// children: [ -// { -// path: '/settings', +// children: { +// '/settings': { // element, -// children: [ -// { -// path: '/settings/agent-configuration', +// children: { +// '/settings/agent-configuration': { // element, // }, -// { -// path: '/settings/agent-configuration/create', +// '/settings/agent-configuration/create': { // element, // params: t.partial({ // query: t.partial({ @@ -303,8 +217,7 @@ type MapRoutes = TRoutes extends [Route] // }), // }), // }, -// { -// path: '/settings/agent-configuration/edit', +// '/settings/agent-configuration/edit': { // element, // params: t.partial({ // query: t.partial({ @@ -312,34 +225,27 @@ type MapRoutes = TRoutes extends [Route] // }), // }), // }, -// { -// path: '/settings/apm-indices', +// '/settings/apm-indices': { // element, // }, -// { -// path: '/settings/custom-links', +// '/settings/custom-links': { // element, // }, -// { -// path: '/settings/schema', +// '/settings/schema': { // element, // }, -// { -// path: '/settings/anomaly-detection', +// '/settings/anomaly-detection': { // element, // }, -// { -// path: '/settings/agent-keys', +// '/settings/agent-keys': { // element, // }, -// { -// path: '/settings', +// '/settings': { // element, // }, -// ], +// }, // }, -// { -// path: '/services/:serviceName', +// '/services/:serviceName': { // element, // params: t.intersection([ // t.type({ @@ -360,29 +266,23 @@ type MapRoutes = TRoutes extends [Route] // }), // }), // ]), -// children: [ -// { -// path: '/services/:serviceName/overview', +// children: { +// '/services/:serviceName/overview': { // element, // }, -// { -// path: '/services/:serviceName/transactions', +// '/services/:serviceName/transactions': { // element, // }, -// { -// path: '/services/:serviceName/transactions/view', +// '/services/:serviceName/transactions/view': { // element, // }, -// { -// path: '/services/:serviceName/dependencies', +// '/services/:serviceName/dependencies': { // element, // }, -// { -// path: '/services/:serviceName/errors', +// '/services/:serviceName/errors': { // element, -// children: [ -// { -// path: '/services/:serviceName/errors/:groupId', +// children: { +// '/services/:serviceName/errors/:groupId': { // element, // params: t.type({ // path: t.type({ @@ -390,8 +290,7 @@ type MapRoutes = TRoutes extends [Route] // }), // }), // }, -// { -// path: '/services/:serviceName/errors', +// '/services/:serviceName/errors': { // element, // params: t.partial({ // query: t.partial({ @@ -402,46 +301,37 @@ type MapRoutes = TRoutes extends [Route] // }), // }), // }, -// ], +// }, // }, -// { -// path: '/services/:serviceName/metrics', +// '/services/:serviceName/metrics': { // element, // }, -// { -// path: '/services/:serviceName/nodes', +// '/services/:serviceName/nodes': { // element, -// children: [ -// { -// path: '/services/{serviceName}/nodes/{serviceNodeName}/metrics', +// children: { +// '/services/{serviceName}/nodes/{serviceNodeName}/metrics': { // element, // }, -// { -// path: '/services/:serviceName/nodes', +// '/services/:serviceName/nodes': { // element, // }, -// ], +// }, // }, -// { -// path: '/services/:serviceName/service-map', +// '/services/:serviceName/service-map': { // element, // }, -// { -// path: '/services/:serviceName/logs', +// '/services/:serviceName/logs': { // element, // }, -// { -// path: '/services/:serviceName/profiling', +// '/services/:serviceName/profiling': { // element, // }, -// { -// path: '/services/:serviceName', +// '/services/:serviceName': { // element, // }, -// ], +// }, // }, -// { -// path: '/', +// '/': { // element, // params: t.partial({ // query: t.partial({ @@ -449,55 +339,47 @@ type MapRoutes = TRoutes extends [Route] // rangeTo: t.string, // }), // }), -// children: [ -// { -// path: '/services', +// children: { +// '/services': { // element, // }, -// { -// path: '/traces', +// '/traces': { // element, // }, -// { -// path: '/service-map', +// '/service-map': { // element, // }, -// { -// path: '/backends', +// '/backends': { // element, -// children: [ -// { -// path: '/backends/{backendName}/overview', +// children: { +// '/backends/{backendName}/overview': { // element, // }, -// { -// path: '/backends/overview', +// '/backends/overview': { // element, // }, -// { -// path: '/backends', +// '/backends': { // element, // }, -// ], +// }, // }, -// { -// path: '/', +// '/': { // element, // }, -// ], +// }, // }, -// ], +// }, // }, -// ] as const); +// }; // type Routes = typeof routes; -// type Mapped = keyof MapRoutes; +// type Mapped = MapRoutes; // type Paths = PathsOf; -// type Bar = ValuesType>['route']['path']; +// type Bar = Match; // type Foo = OutputOf; -// // type Baz = OutputOf; +// type Baz = OutputOf; // const { path }: Foo = {} as any; @@ -505,4 +387,7 @@ type MapRoutes = TRoutes extends [Route] // return {} as any; // } -// // const params = _useApmParams('/services/:serviceName/nodes/*'); +// const { +// path: { serviceName }, +// query: { comparisonType }, +// } = _useApmParams('/services/:serviceName/nodes/*'); diff --git a/packages/kbn-typed-react-router-config/src/unconst.ts b/packages/kbn-typed-react-router-config/src/unconst.ts deleted file mode 100644 index d10c8290e20e9..0000000000000 --- a/packages/kbn-typed-react-router-config/src/unconst.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import * as t from 'io-ts'; -import { DeepReadonly } from 'utility-types'; - -export type MaybeConst = TObject extends [object] - ? [DeepReadonly | TObject] - : TObject extends [object, ...infer TTail] - ? [DeepReadonly | TObject, ...(TTail extends object[] ? MaybeConst : [])] - : TObject extends object[] - ? DeepReadonly - : TObject extends object - ? [DeepReadonly | TObject] - : []; - -export type Unconst = T extends React.ReactElement - ? React.ReactElement - : T extends t.Type - ? T - : T extends readonly [any] - ? [Unconst] - : T extends readonly [any, any] - ? [Unconst, Unconst] - : T extends readonly [any, any, any] - ? [Unconst, Unconst, Unconst] - : T extends readonly [any, any, any, any] - ? [Unconst, Unconst, Unconst, Unconst] - : T extends readonly [any, any, any, any, any] - ? [Unconst, Unconst, Unconst, Unconst, Unconst] - : T extends readonly [any, any, any, any, any, any] - ? [Unconst, Unconst, Unconst, Unconst, Unconst, Unconst] - : T extends readonly [any, any, any, any, any, any, any] - ? [ - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst - ] - : T extends readonly [any, any, any, any, any, any, any, any] - ? [ - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst - ] - : T extends readonly [any, any, any, any, any, any, any, any, any] - ? [ - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst - ] - : T extends readonly [any, any, any, any, any, any, any, any, any, any] - ? [ - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst, - Unconst - ] - : T extends readonly [infer U, ...infer V] - ? [Unconst, ...Unconst] - : T extends Record - ? { -readonly [key in keyof T]: Unconst } - : T; - -export function unconst(value: T): Unconst { - return value as Unconst; -} diff --git a/packages/kbn-typed-react-router-config/src/use_router.tsx b/packages/kbn-typed-react-router-config/src/use_router.tsx index c78e85650f26d..f3a6c396d37d4 100644 --- a/packages/kbn-typed-react-router-config/src/use_router.tsx +++ b/packages/kbn-typed-react-router-config/src/use_router.tsx @@ -7,19 +7,19 @@ */ import React, { createContext, useContext } from 'react'; -import { Route, Router } from './types'; +import { RouteMap, Router } from './types'; -const RouterContext = createContext | undefined>(undefined); +const RouterContext = createContext | undefined>(undefined); export const RouterContextProvider = ({ router, children, }: { - router: Router; + router: Router; children: React.ReactNode; }) => {children}; -export function useRouter(): Router { +export function useRouter(): Router { const router = useContext(RouterContext); if (!router) { diff --git a/src/plugins/vis_types/timelion/public/helpers/panel_utils.ts b/src/plugins/vis_types/timelion/public/helpers/panel_utils.ts index 98be5efc55a26..80078d9e2672e 100644 --- a/src/plugins/vis_types/timelion/public/helpers/panel_utils.ts +++ b/src/plugins/vis_types/timelion/public/helpers/panel_utils.ts @@ -68,7 +68,7 @@ export const MAIN_GROUP_ID = 1; export const withStaticPadding = (domain: AxisSpec['domain']): AxisSpec['domain'] => ({ ...domain, - padding: 50, + padding: 20, paddingUnit: 'pixel', } as unknown as AxisSpec['domain']); diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js index b177ef632e210..2790130c553b5 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js @@ -266,6 +266,7 @@ class TimeseriesVisualization extends Component { legend={Boolean(model.show_legend)} legendPosition={model.legend_position} truncateLegend={Boolean(model.truncate_legend)} + ignoreDaylightTime={Boolean(model.ignore_daylight_time)} maxLegendLines={model.max_lines_legend} tooltipMode={model.tooltip_mode} xAxisFormatter={this.xAxisFormatter(interval)} diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.test.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.test.js index cf4c327df3d77..12ae70cca1036 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.test.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.test.js @@ -10,11 +10,12 @@ import React from 'react'; import { shallow } from 'enzyme'; import { TimeSeries } from '../../../visualizations/views/timeseries'; import TimeseriesVisualization from './vis'; -import { setFieldFormats } from '../../../../services'; +import { setFieldFormats, setCharts, setUISettings } from '../../../../services'; import { createFieldFormatter } from '../../lib/create_field_formatter'; import { FORMATS_UI_SETTINGS } from '../../../../../../../field_formats/common'; import { METRIC_TYPES } from '../../../../../../../data/common'; import { getFieldFormatsRegistry } from '../../../../../../../data/public/test_utils'; +import { MULTILAYER_TIME_AXIS_STYLE } from '../../../../../../../charts/public'; jest.mock('../../../../../../../data/public/services', () => ({ getUiSettings: () => ({ get: jest.fn() }), @@ -35,12 +36,47 @@ describe('TimeseriesVisualization', () => { }) ); - const setupTimeSeriesProps = (formatters, valueTemplates) => { + setCharts({ + theme: { + useChartsTheme: () => ({ + axes: { + tickLabel: { + padding: { + inner: 0, + }, + }, + }, + }), + useChartsBaseTheme: () => ({ + axes: { + tickLabel: { + padding: { + inner: 0, + }, + }, + }, + }), + }, + activeCursor: {}, + }); + + setUISettings({ + get: () => ({}), + isDefault: () => true, + }); + + const renderShallow = (formatters, valueTemplates, modelOverwrites) => { const series = formatters.map((formatter, index) => ({ id: id + index, + label: '', formatter, value_template: valueTemplates?.[index], data: [], + lines: { + show: true, + }, + points: {}, + color: '#000000', metrics: [ { type: METRIC_TYPES.AVG, @@ -63,6 +99,7 @@ describe('TimeseriesVisualization', () => { id, series, use_kibana_indexes: true, + ...modelOverwrites, }} visData={{ [id]: { @@ -75,9 +112,26 @@ describe('TimeseriesVisualization', () => { /> ); - return timeSeriesVisualization.find(TimeSeries).props(); + return timeSeriesVisualization; + }; + + const setupTimeSeriesProps = (formatters, valueTemplates) => { + return renderShallow(formatters, valueTemplates).find(TimeSeries).props(); }; + test('should enable new time axis if ignore daylight time setting is switched off', () => { + const component = renderShallow(['byte'], undefined, { ignore_daylight_time: false }); + console.log(component.find('TimeSeries').dive().debug()); + const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]'); + expect(xAxis.prop('style')).toEqual(MULTILAYER_TIME_AXIS_STYLE); + }); + + test('should disable new time axis for ignore daylight time setting', () => { + const component = renderShallow(['byte'], undefined, { ignore_daylight_time: true }); + const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]'); + expect(xAxis.prop('style')).toBeUndefined(); + }); + test('should return byte formatted value from yAxis formatter for single byte series', () => { const timeSeriesProps = setupTimeSeriesProps(['byte']); diff --git a/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js b/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js index 9dfddd3457d44..c8e845ce6b54c 100644 --- a/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js +++ b/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js @@ -77,6 +77,7 @@ export const TimeSeries = ({ interval, isLastBucketDropped, useLegacyTimeAxis, + ignoreDaylightTime, }) => { // If the color isn't configured by the user, use the color mapping service // to assign a color from the Kibana palette. Colors will be shared across the @@ -152,7 +153,9 @@ export const TimeSeries = ({ const shouldUseNewTimeAxis = series.every( ({ stack, bars, lines }) => (bars?.show && stack !== STACKED_OPTIONS.NONE) || lines?.show - ) && !useLegacyTimeAxis; + ) && + !useLegacyTimeAxis && + !ignoreDaylightTime; return ( diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js index 109e552ce89a1..429050fab36cc 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js @@ -7,9 +7,18 @@ */ import { startsWith } from 'lodash'; -import moment from 'moment'; +import moment from 'moment-timezone'; -export function timeShift(resp, panel, series) { +export function timeShift( + resp, + panel, + series, + meta, + extractFields, + fieldFormatService, + cachedIndexPatternFetcher, + timezone +) { return (next) => (results) => { if (/^([+-]?[\d]+)([shmdwMy]|ms)$/.test(series.offset_time)) { const matches = series.offset_time.match(/^([+-]?[\d]+)([shmdwMy]|ms)$/); @@ -18,14 +27,29 @@ export function timeShift(resp, panel, series) { const offsetValue = matches[1]; const offsetUnit = matches[2]; + let defaultTimezone; + if (!panel.ignore_daylight_time) { + // the datemath plugin always parses dates by using the current default moment time zone. + // to use the configured time zone, we are switching just for the bounds calculation. + defaultTimezone = moment().zoneName(); + moment.tz.setDefault(timezone); + } + results.forEach((item) => { if (startsWith(item.id, series.id)) { item.data = item.data.map((row) => [ - moment.utc(row[0]).add(offsetValue, offsetUnit).valueOf(), + (panel.ignore_daylight_time ? moment.utc : moment)(row[0]) + .add(offsetValue, offsetUnit) + .valueOf(), row[1], ]); } }); + + if (!panel.ignore_daylight_time) { + // reset default moment timezone + moment.tz.setDefault(defaultTimezone); + } } } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js index e00f4aad24130..7fff2603cf47a 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js @@ -73,4 +73,59 @@ describe('timeShift(resp, panel, series)', () => { [1483225210000 + 3600000, 2], ]); }); + + test('shifts in right timezone', async () => { + series.offset_time = '1d'; + const dateBeforeDST = new Date('2022-03-26T12:00:00.000Z').valueOf(); + const dateAfterDST = new Date('2022-03-28T12:00:00.000Z').valueOf(); + resp.aggregations.test.timeseries.buckets[0].key = dateBeforeDST; + resp.aggregations.test.timeseries.buckets[1].key = dateAfterDST; + const next = await timeShift( + resp, + panel, + series, + {}, + undefined, + undefined, + undefined, + 'Europe/Berlin' + )((results) => results); + const results = await stdMetric(resp, panel, series, {})(next)([]); + + expect(results).toHaveLength(1); + expect(results[0].data).toEqual([ + // only 23h in a day because it goes over the DST switch + [dateBeforeDST + 1000 * 60 * 60 * 23, 1], + // regular 24h in a day + [dateAfterDST + 1000 * 60 * 60 * 24, 2], + ]); + }); + + test('shifts in utc if ignore daylight time is set', async () => { + series.offset_time = '1d'; + panel.ignore_daylight_time = 1; + const dateBeforeDST = new Date('2022-03-26T12:00:00.000Z').valueOf(); + const dateAfterDST = new Date('2022-03-28T12:00:00.000Z').valueOf(); + resp.aggregations.test.timeseries.buckets[0].key = dateBeforeDST; + resp.aggregations.test.timeseries.buckets[1].key = dateAfterDST; + const next = await timeShift( + resp, + panel, + series, + {}, + undefined, + undefined, + undefined, + 'Europe/Berlin' + )((results) => results); + const results = await stdMetric(resp, panel, series, {})(next)([]); + + expect(results).toHaveLength(1); + expect(results[0].data).toEqual([ + // still 24h shift because DST is ignored + [dateBeforeDST + 1000 * 60 * 60 * 24, 1], + // regular 24h in a day + [dateAfterDST + 1000 * 60 * 60 * 24, 2], + ]); + }); }); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/series/handle_response_body.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/series/handle_response_body.ts index 415844abeedaf..5244bca66a5b3 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/series/handle_response_body.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/series/handle_response_body.ts @@ -59,7 +59,8 @@ export function handleResponseBody( meta, extractFields, fieldFormatService, - services.cachedIndexPatternFetcher + services.cachedIndexPatternFetcher, + req.body.timerange.timezone ); return await processor([]); diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index 3f873850ff193..7a8a36bec56d7 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -92,7 +92,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); - it('should add comma after previous non empty line on autocomplete', async () => { + // Flaky, see https://github.com/elastic/kibana/issues/123556 + it.skip('should add comma after previous non empty line on autocomplete', async () => { const LINE_NUMBER = 2; await PageObjects.console.dismissTutorial(); diff --git a/test/functional/apps/visualize/_timelion.ts b/test/functional/apps/visualize/_timelion.ts index f8991e17319bd..e10ba03a0e19f 100644 --- a/test/functional/apps/visualize/_timelion.ts +++ b/test/functional/apps/visualize/_timelion.ts @@ -171,7 +171,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(firstAxesLabels).to.eql(['12.2GB', '12.21GB']); expect(secondAxesLabels).to.eql(['5.59KB', '5.6KB']); expect(thirdAxesLabels.toString()).to.be( - 'BYTES_5721,BYTES_5722,BYTES_5723,BYTES_5724,BYTES_5725,BYTES_5726,BYTES_5727,BYTES_5728,BYTES_5729,BYTES_5730,BYTES_5731,BYTES_5732,BYTES_5733' + 'BYTES_5722,BYTES_5723,BYTES_5724,BYTES_5725,BYTES_5726,BYTES_5727,BYTES_5728,BYTES_5729,BYTES_5730,BYTES_5731,BYTES_5732,BYTES_5733' ); }); diff --git a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts index a7a00034e7064..3895c90d4a6c2 100644 --- a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts +++ b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts @@ -25,6 +25,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "execute-start"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleType, action: 'execute-start', @@ -50,6 +51,13 @@ describe('createAlertEventLogRecordObject', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', + }, + }, + }, saved_objects: [ { id: '1', @@ -76,6 +84,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "recovered-instance"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleName: 'test name', ruleType, @@ -109,6 +118,13 @@ describe('createAlertEventLogRecordObject', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', + }, + }, + }, alerting: { action_group_id: 'group 1', action_subgroup: 'subgroup value', @@ -138,6 +154,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "execute-action"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleName: 'test name', ruleType, @@ -176,6 +193,13 @@ describe('createAlertEventLogRecordObject', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', + }, + }, + }, alerting: { action_group_id: 'group 1', action_subgroup: 'subgroup value', diff --git a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts index e06b5bf893bac..95e33d394fbd2 100644 --- a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts +++ b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts @@ -12,6 +12,7 @@ import { UntypedNormalizedRuleType } from '../rule_type_registry'; export type Event = Exclude; interface CreateAlertEventLogRecordParams { + executionId?: string; ruleId: string; ruleType: UntypedNormalizedRuleType; action: string; @@ -36,7 +37,18 @@ interface CreateAlertEventLogRecordParams { } export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecordParams): Event { - const { ruleType, action, state, message, task, ruleId, group, subgroup, namespace } = params; + const { + executionId, + ruleType, + action, + state, + message, + task, + ruleId, + group, + subgroup, + namespace, + } = params; const alerting = params.instanceId || group || subgroup ? { @@ -59,6 +71,17 @@ export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecor }, kibana: { ...(alerting ? alerting : {}), + ...(executionId + ? { + alert: { + rule: { + execution: { + uuid: executionId, + }, + }, + }, + } + : {}), saved_objects: params.savedObjects.map((so) => ({ ...(so.relation ? { rel: so.relation } : {}), type: so.type, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index a5b9f1d928e81..9c3e5872c76e1 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -21,6 +21,10 @@ import { getBeforeSetup, setGlobalDate } from './lib'; import { eventLoggerMock } from '../../../../event_log/server/event_logger.mock'; import { TaskStatus } from '../../../../task_manager/server'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const taskManager = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index 69b094585d703..71ec12e29a9dd 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -73,6 +73,7 @@ const createExecutionHandlerParams: jest.Mocked< spaceId: 'test1', ruleId: '1', ruleName: 'name-of-alert', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', tags: ['tag-A', 'tag-B'], apiKey: 'MTIzOmFiYw==', kibanaBaseUrl: 'http://localhost:5601', @@ -173,6 +174,13 @@ test('enqueues execution per selected action', async () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts index 112cb949e3ad7..58f8089890c87 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts @@ -36,6 +36,7 @@ export interface CreateExecutionHandlerOptions< > { ruleId: string; ruleName: string; + executionId: string; tags?: string[]; actionsPlugin: ActionsPluginStartContract; actions: AlertAction[]; @@ -83,6 +84,7 @@ export function createExecutionHandler< logger, ruleId, ruleName, + executionId, tags, actionsPlugin, actions: ruleActions, @@ -206,6 +208,7 @@ export function createExecutionHandler< ruleId, ruleType: ruleType as UntypedNormalizedRuleType, action: EVENT_LOG_ACTIONS.executeAction, + executionId, instanceId: alertId, group: actionGroup, subgroup: actionSubgroup, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 61d41e674c209..a466583cd3bd3 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -41,6 +41,10 @@ import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { ExecuteOptions } from '../../../actions/server/create_execute_function'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const ruleType: jest.Mocked = { id: 'test', name: 'My test rule', @@ -323,6 +327,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -484,6 +495,13 @@ describe('Task Runner', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -515,6 +533,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', action_subgroup: 'subDefault', @@ -549,6 +574,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', action_subgroup: 'subDefault', @@ -576,6 +608,13 @@ describe('Task Runner', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -611,6 +650,13 @@ describe('Task Runner', () => { expect(eventLogger.logEvent).toHaveBeenNthCalledWith(5, { event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { status: 'active', }, @@ -707,6 +753,13 @@ describe('Task Runner', () => { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', }, + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -734,6 +787,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -767,6 +827,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -799,6 +866,13 @@ describe('Task Runner', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { status: 'active', }, @@ -963,6 +1037,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -998,6 +1079,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1033,6 +1121,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -1302,6 +1397,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -1337,6 +1439,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1373,6 +1482,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1407,6 +1523,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1448,6 +1571,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -1597,6 +1727,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -1633,6 +1770,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -1668,6 +1812,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1702,6 +1853,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "recovered", "instance_id": "2", @@ -1742,6 +1900,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1783,6 +1948,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -2165,6 +2337,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2201,6 +2380,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -2237,6 +2423,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -2272,6 +2465,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -2546,6 +2746,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2584,6 +2791,13 @@ describe('Task Runner', () => { "reason": "execute", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2666,6 +2880,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2704,6 +2925,13 @@ describe('Task Runner', () => { "reason": "decrypt", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2795,6 +3023,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2833,6 +3068,13 @@ describe('Task Runner', () => { "reason": "license", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2924,6 +3166,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2962,6 +3211,13 @@ describe('Task Runner', () => { "reason": "unknown", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "error", }, @@ -3052,6 +3308,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3090,6 +3353,13 @@ describe('Task Runner', () => { "reason": "read", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "error", }, @@ -3358,6 +3628,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3393,6 +3670,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3429,6 +3713,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3465,6 +3756,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3501,6 +3799,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3536,6 +3841,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -3643,6 +3955,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3678,6 +3997,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3714,6 +4040,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3749,6 +4082,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -3848,6 +4188,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3881,6 +4228,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3915,6 +4269,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3950,6 +4311,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "active", }, @@ -4044,6 +4412,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -4080,6 +4455,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "1", }, @@ -4116,6 +4498,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -4150,6 +4539,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "ok", }, @@ -4246,6 +4642,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -4279,6 +4682,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "1", }, @@ -4312,6 +4722,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -4346,6 +4763,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "status": "ok", }, @@ -4506,6 +4930,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -4596,6 +5027,13 @@ describe('Task Runner', () => { category: ['alerts'], }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' }, ], @@ -4618,6 +5056,13 @@ describe('Task Runner', () => { outcome: 'failure', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' }, ], diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index b4fa5a1927fee..9640dd9038ce7 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -8,6 +8,7 @@ import apm from 'elastic-apm-node'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { Dictionary, pickBy, mapValues, without, cloneDeep } from 'lodash'; import type { Request } from '@hapi/hapi'; +import uuid from 'uuid'; import { addSpaceIdToPath } from '../../../spaces/server'; import { Logger, KibanaRequest } from '../../../../../src/core/server'; import { TaskRunnerContext } from './task_runner_factory'; @@ -106,6 +107,7 @@ export class TaskRunner< ActionGroupIds, RecoveryActionGroupId >; + private readonly executionId: string; private readonly ruleTypeRegistry: RuleTypeRegistry; private searchAbortController: AbortController; private cancelled: boolean; @@ -131,6 +133,7 @@ export class TaskRunner< this.ruleTypeRegistry = context.ruleTypeRegistry; this.searchAbortController = new AbortController(); this.cancelled = false; + this.executionId = uuid.v4(); } async getDecryptedAttributes( @@ -209,6 +212,7 @@ export class TaskRunner< ruleId, ruleName, tags, + executionId: this.executionId, logger: this.logger, actionsPlugin: this.context.actionsPlugin, apiKey, @@ -324,6 +328,7 @@ export class TaskRunner< updatedRuleTypeState = await this.context.executionContext.withContext(ctx, () => this.ruleType.executor({ alertId: ruleId, + executionId: this.executionId, services: { ...services, alertInstanceFactory: createAlertInstanceFactory< @@ -411,6 +416,7 @@ export class TaskRunner< if (this.shouldLogAndScheduleActionsForAlerts()) { generateNewAndRecoveredAlertEvents({ eventLogger, + executionId: this.executionId, originalAlerts, currentAlerts: alertsWithScheduledActions, recoveredAlerts, @@ -612,6 +618,7 @@ export class TaskRunner< ruleType: this.ruleType as UntypedNormalizedRuleType, action: EVENT_LOG_ACTIONS.execute, namespace, + executionId: this.executionId, task: { scheduled: this.taskInstance.runAt.toISOString(), scheduleDelay: Millis2Nanos * scheduleDelay, @@ -785,6 +792,13 @@ export class TaskRunner< this.ruleType.ruleTaskTimeout }`, kibana: { + alert: { + rule: { + execution: { + uuid: this.executionId, + }, + }, + }, saved_objects: [ { rel: SAVED_OBJECT_REL_PRIMARY, @@ -883,6 +897,7 @@ interface GenerateNewAndRecoveredAlertEventsParams< InstanceContext extends AlertInstanceContext > { eventLogger: IEventLogger; + executionId: string; originalAlerts: Dictionary>; currentAlerts: Dictionary>; recoveredAlerts: Dictionary>; @@ -911,6 +926,7 @@ function generateNewAndRecoveredAlertEvents< >(params: GenerateNewAndRecoveredAlertEventsParams) { const { eventLogger, + executionId, ruleId, namespace, currentAlerts, @@ -990,6 +1006,13 @@ function generateNewAndRecoveredAlertEvents< ...(state?.duration !== undefined ? { duration: state.duration as number } : {}), }, kibana: { + alert: { + rule: { + execution: { + uuid: executionId, + }, + }, + }, alerting: { instance_id: alertId, ...(group ? { action_group_id: group } : {}), diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 3e3c3351a8e67..e24be639c7fcc 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -32,6 +32,10 @@ import { Alert, RecoveredActionGroup } from '../../common'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const ruleType: jest.Mocked = { id: 'test', name: 'My test rule', @@ -208,6 +212,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -236,6 +247,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -261,6 +279,13 @@ describe('Task Runner Cancel', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { status: 'ok', }, @@ -437,6 +462,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -465,6 +497,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -491,6 +530,13 @@ describe('Task Runner Cancel', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { status: 'active', }, @@ -553,6 +599,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -582,6 +635,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -609,6 +669,13 @@ describe('Task Runner Cancel', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -642,6 +709,13 @@ describe('Task Runner Cancel', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -666,6 +740,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -697,6 +778,13 @@ describe('Task Runner Cancel', () => { expect(eventLogger.logEvent).toHaveBeenNthCalledWith(6, { event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { status: 'active', }, diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 866c8665ddb65..93ee520c7126a 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -90,6 +90,7 @@ export interface AlertExecutorOptions< ActionGroupIds extends string = never > { alertId: string; + executionId: string; startedAt: Date; previousStartedAt: Date | null; services: AlertServices; diff --git a/x-pack/plugins/apm/common/environment_rt.ts b/x-pack/plugins/apm/common/environment_rt.ts index 67d1a6ce6fa64..dd07bb9f47318 100644 --- a/x-pack/plugins/apm/common/environment_rt.ts +++ b/x-pack/plugins/apm/common/environment_rt.ts @@ -5,7 +5,7 @@ * 2.0. */ import * as t from 'io-ts'; -import { nonEmptyStringRt } from '@kbn/io-ts-utils/non_empty_string_rt'; +import { nonEmptyStringRt } from '@kbn/io-ts-utils'; import { ENVIRONMENT_ALL, ENVIRONMENT_NOT_DEFINED, diff --git a/x-pack/plugins/apm/public/application/uxApp.tsx b/x-pack/plugins/apm/public/application/uxApp.tsx index fa29f04fccbad..f9883ca348c51 100644 --- a/x-pack/plugins/apm/public/application/uxApp.tsx +++ b/x-pack/plugins/apm/public/application/uxApp.tsx @@ -90,7 +90,7 @@ function UxApp() { ); } -const uxRouter = createRouter([]); +const uxRouter = createRouter({}); export function UXAppRoot({ appMountParameters, diff --git a/x-pack/plugins/apm/public/components/app/backend_inventory/index.tsx b/x-pack/plugins/apm/public/components/app/backend_inventory/index.tsx index 433d187bda0b3..f749927826231 100644 --- a/x-pack/plugins/apm/public/components/app/backend_inventory/index.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_inventory/index.tsx @@ -19,7 +19,6 @@ export function BackendInventory() { const { query: { environment }, } = useApmParams('/backends'); - const kueryBarBoolFilter = getKueryBarBoolFilter({ environment, }); diff --git a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx index 7e6ee849fdb0b..daab3003b18dc 100644 --- a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx +++ b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { createRouter, Outlet, route } from '@kbn/typed-react-router-config'; +import { createRouter, Outlet } from '@kbn/typed-react-router-config'; import * as t from 'io-ts'; import React from 'react'; import { Breadcrumb } from '../app/breadcrumb'; @@ -19,9 +19,8 @@ import { settings } from './settings'; * The array of route definitions to be used when the application * creates the routes. */ -const apmRoutes = route([ - { - path: '/link-to/transaction/{transactionId}', +const apmRoutes = { + '/link-to/transaction/{transactionId}': { element: , params: t.intersection([ t.type({ @@ -37,8 +36,7 @@ const apmRoutes = route([ }), ]), }, - { - path: '/link-to/trace/{traceId}', + '/link-to/trace/{traceId}': { element: , params: t.intersection([ t.type({ @@ -54,16 +52,19 @@ const apmRoutes = route([ }), ]), }, - { - path: '/', + '/': { element: ( ), - children: [settings, serviceDetail, home], + children: { + ...settings, + ...serviceDetail, + ...home, + }, }, -] as const); +}; export type ApmRoutes = typeof apmRoutes; diff --git a/x-pack/plugins/apm/public/components/routing/home/index.tsx b/x-pack/plugins/apm/public/components/routing/home/index.tsx index e70cb31eef88f..efde391467dfd 100644 --- a/x-pack/plugins/apm/public/components/routing/home/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/home/index.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { Outlet } from '@kbn/typed-react-router-config'; import * as t from 'io-ts'; import React from 'react'; -import { toBooleanRt } from '@kbn/io-ts-utils/to_boolean_rt'; +import { toBooleanRt } from '@kbn/io-ts-utils'; import { RedirectTo } from '../redirect_to'; import { comparisonTypeRt } from '../../../../common/runtime_types/comparison_type_rt'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; @@ -30,15 +30,26 @@ function page({ path: TPath; element: React.ReactElement; title: string; -}): { path: TPath; element: React.ReactElement } { +}): Record< + TPath, + { + element: React.ReactElement; + } +> { return { - path, - element: ( - - {element} - - ), - }; + [path]: { + element: ( + + {element} + + ), + }, + } as Record< + TPath, + { + element: React.ReactElement; + } + >; } export const ServiceInventoryTitle = i18n.translate( @@ -56,88 +67,85 @@ export const DependenciesInventoryTitle = i18n.translate( ); export const home = { - path: '/', - element: , - params: t.type({ - query: t.intersection([ - environmentRt, - t.type({ - rangeFrom: t.string, - rangeTo: t.string, - kuery: t.string, - }), - t.partial({ - refreshPaused: t.union([t.literal('true'), t.literal('false')]), - refreshInterval: t.string, - comparisonEnabled: toBooleanRt, - comparisonType: comparisonTypeRt, - }), - ]), - }), - defaults: { - query: { - environment: ENVIRONMENT_ALL.value, - kuery: '', - }, - }, - children: [ - page({ - path: '/services', - title: ServiceInventoryTitle, - element: , + '/': { + element: , + params: t.type({ + query: t.intersection([ + environmentRt, + t.type({ + rangeFrom: t.string, + rangeTo: t.string, + kuery: t.string, + }), + t.partial({ + refreshPaused: t.union([t.literal('true'), t.literal('false')]), + refreshInterval: t.string, + comparisonEnabled: toBooleanRt, + comparisonType: comparisonTypeRt, + }), + ]), }), - page({ - path: '/traces', - title: i18n.translate('xpack.apm.views.traceOverview.title', { - defaultMessage: 'Traces', + defaults: { + query: { + environment: ENVIRONMENT_ALL.value, + kuery: '', + }, + }, + children: { + ...page({ + path: '/services', + title: ServiceInventoryTitle, + element: , }), - element: , - }), - page({ - path: '/service-map', - title: i18n.translate('xpack.apm.views.serviceMap.title', { - defaultMessage: 'Service Map', + ...page({ + path: '/traces', + title: i18n.translate('xpack.apm.views.traceOverview.title', { + defaultMessage: 'Traces', + }), + element: , }), - element: , - }), - { - path: '/backends', - element: , - params: t.partial({ - query: t.partial({ - comparisonEnabled: toBooleanRt, - comparisonType: comparisonTypeRt, + ...page({ + path: '/service-map', + title: i18n.translate('xpack.apm.views.serviceMap.title', { + defaultMessage: 'Service Map', }), + element: , }), - children: [ - { - path: '/backends/{backendName}/overview', - element: , - params: t.type({ - path: t.type({ - backendName: t.string, - }), + '/backends': { + element: , + params: t.partial({ + query: t.partial({ + comparisonEnabled: toBooleanRt, + comparisonType: comparisonTypeRt, }), - }, - { - path: '/backends/overview', - element: , - params: t.type({ - query: t.type({ - backendName: t.string, + }), + children: { + '/backends/{backendName}/overview': { + element: , + params: t.type({ + path: t.type({ + backendName: t.string, + }), + }), + }, + '/backends/overview': { + element: , + params: t.type({ + query: t.type({ + backendName: t.string, + }), }), + }, + ...page({ + path: '/backends', + title: DependenciesInventoryTitle, + element: , }), }, - page({ - path: '/backends', - title: DependenciesInventoryTitle, - element: , - }), - ], + }, + '/': { + element: , + }, }, - { - path: '/', - element: , - }, - ], -} as const; + }, +}; diff --git a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx index 713292c633891..6514c8288be0e 100644 --- a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { Outlet } from '@kbn/typed-react-router-config'; -import { toBooleanRt } from '@kbn/io-ts-utils/to_boolean_rt'; +import { toBooleanRt } from '@kbn/io-ts-utils'; import { comparisonTypeRt } from '../../../../common/runtime_types/comparison_type_rt'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; import { environmentRt } from '../../../../common/environment_rt'; @@ -29,14 +29,12 @@ import { ServiceDependencies } from '../../app/service_dependencies'; import { ServiceLogs } from '../../app/service_logs'; import { InfraOverview } from '../../app/infra_overview'; -function page({ - path, +function page({ title, tab, element, searchBarOptions, }: { - path: TPath; title: string; tab: React.ComponentProps['selectedTab']; element: React.ReactElement; @@ -48,10 +46,8 @@ function page({ }; }): { element: React.ReactElement; - path: TPath; } { return { - path, element: ( ({ {element} ), - } as any; + }; } export const serviceDetail = { - path: '/services/{serviceName}', - element: , - params: t.intersection([ - t.type({ - path: t.type({ - serviceName: t.string, - }), - }), - t.type({ - query: t.intersection([ - environmentRt, - t.type({ - rangeFrom: t.string, - rangeTo: t.string, - kuery: t.string, - }), - t.partial({ - comparisonEnabled: toBooleanRt, - comparisonType: comparisonTypeRt, - latencyAggregationType: t.string, - transactionType: t.string, - refreshPaused: t.union([t.literal('true'), t.literal('false')]), - refreshInterval: t.string, + '/services/{serviceName}': { + element: , + params: t.intersection([ + t.type({ + path: t.type({ + serviceName: t.string, }), - ]), - }), - ]), - defaults: { - query: { - kuery: '', - environment: ENVIRONMENT_ALL.value, - }, - }, - children: [ - page({ - path: '/services/{serviceName}/overview', - element: , - tab: 'overview', - title: i18n.translate('xpack.apm.views.overview.title', { - defaultMessage: 'Overview', }), - searchBarOptions: { - showTransactionTypeSelector: true, - showTimeComparison: true, + t.type({ + query: t.intersection([ + environmentRt, + t.type({ + rangeFrom: t.string, + rangeTo: t.string, + kuery: t.string, + }), + t.partial({ + comparisonEnabled: toBooleanRt, + comparisonType: comparisonTypeRt, + latencyAggregationType: t.string, + transactionType: t.string, + refreshPaused: t.union([t.literal('true'), t.literal('false')]), + refreshInterval: t.string, + }), + ]), + }), + ]), + defaults: { + query: { + kuery: '', + environment: ENVIRONMENT_ALL.value, }, - }), - { - ...page({ - path: '/services/{serviceName}/transactions', - tab: 'transactions', - title: i18n.translate('xpack.apm.views.transactions.title', { - defaultMessage: 'Transactions', + }, + children: { + '/services/{serviceName}/overview': page({ + element: , + tab: 'overview', + title: i18n.translate('xpack.apm.views.overview.title', { + defaultMessage: 'Overview', }), - element: , searchBarOptions: { showTransactionTypeSelector: true, showTimeComparison: true, }, }), - children: [ - { - path: '/services/{serviceName}/transactions/view', - element: , - params: t.type({ - query: t.intersection([ - t.type({ - transactionName: t.string, - }), - t.partial({ - traceId: t.string, - transactionId: t.string, - comparisonEnabled: toBooleanRt, - comparisonType: comparisonTypeRt, - }), - ]), + '/services/{serviceName}/transactions': { + ...page({ + tab: 'transactions', + title: i18n.translate('xpack.apm.views.transactions.title', { + defaultMessage: 'Transactions', }), + element: , + searchBarOptions: { + showTransactionTypeSelector: true, + showTimeComparison: true, + }, + }), + children: { + '/services/{serviceName}/transactions/view': { + element: , + params: t.type({ + query: t.intersection([ + t.type({ + transactionName: t.string, + }), + t.partial({ + traceId: t.string, + transactionId: t.string, + comparisonEnabled: toBooleanRt, + comparisonType: comparisonTypeRt, + }), + ]), + }), + }, + '/services/{serviceName}/transactions': { + element: , + }, }, - { - path: '/services/{serviceName}/transactions', - element: , - }, - ], - }, - page({ - path: '/services/{serviceName}/dependencies', - element: , - tab: 'dependencies', - title: i18n.translate('xpack.apm.views.dependencies.title', { - defaultMessage: 'Dependencies', - }), - searchBarOptions: { - showTimeComparison: true, }, - }), - { - ...page({ - path: '/services/{serviceName}/errors', - tab: 'errors', - title: i18n.translate('xpack.apm.views.errors.title', { - defaultMessage: 'Errors', + '/services/{serviceName}/dependencies': page({ + element: , + tab: 'dependencies', + title: i18n.translate('xpack.apm.views.dependencies.title', { + defaultMessage: 'Dependencies', }), - element: , searchBarOptions: { showTimeComparison: true, }, }), - params: t.partial({ - query: t.partial({ - sortDirection: t.string, - sortField: t.string, - pageSize: t.string, - page: t.string, + '/services/{serviceName}/errors': { + ...page({ + tab: 'errors', + title: i18n.translate('xpack.apm.views.errors.title', { + defaultMessage: 'Errors', + }), + element: , + searchBarOptions: { + showTimeComparison: true, + }, }), - }), - children: [ - { - path: '/services/{serviceName}/errors/{groupId}', - element: , - params: t.type({ - path: t.type({ - groupId: t.string, - }), + params: t.partial({ + query: t.partial({ + sortDirection: t.string, + sortField: t.string, + pageSize: t.string, + page: t.string, }), + }), + children: { + '/services/{serviceName}/errors/{groupId}': { + element: , + params: t.type({ + path: t.type({ + groupId: t.string, + }), + }), + }, + '/services/{serviceName}/errors': { + element: , + }, }, - { - path: '/services/{serviceName}/errors', - element: , - }, - ], - }, - page({ - path: '/services/{serviceName}/metrics', - tab: 'metrics', - title: i18n.translate('xpack.apm.views.metrics.title', { - defaultMessage: 'Metrics', - }), - element: , - }), - { - ...page({ - path: '/services/{serviceName}/nodes', - tab: 'nodes', - title: i18n.translate('xpack.apm.views.nodes.title', { - defaultMessage: 'JVMs', + }, + '/services/{serviceName}/metrics': page({ + tab: 'metrics', + title: i18n.translate('xpack.apm.views.metrics.title', { + defaultMessage: 'Metrics', }), - element: , + element: , }), - children: [ - { - path: '/services/{serviceName}/nodes/{serviceNodeName}/metrics', - element: , - params: t.type({ - path: t.type({ - serviceNodeName: t.string, - }), + '/services/{serviceName}/nodes': { + ...page({ + tab: 'nodes', + title: i18n.translate('xpack.apm.views.nodes.title', { + defaultMessage: 'JVMs', }), - }, - { - path: '/services/{serviceName}/nodes', - element: , - params: t.partial({ - query: t.partial({ - sortDirection: t.string, - sortField: t.string, - pageSize: t.string, - page: t.string, + element: , + }), + children: { + '/services/{serviceName}/nodes/{serviceNodeName}/metrics': { + element: , + params: t.type({ + path: t.type({ + serviceNodeName: t.string, + }), }), - }), + }, + '/services/{serviceName}/nodes': { + element: , + params: t.partial({ + query: t.partial({ + sortDirection: t.string, + sortField: t.string, + pageSize: t.string, + page: t.string, + }), + }), + }, }, - ], - }, - page({ - path: '/services/{serviceName}/service-map', - tab: 'service-map', - title: i18n.translate('xpack.apm.views.serviceMap.title', { - defaultMessage: 'Service Map', - }), - element: , - searchBarOptions: { - hidden: true, }, - }), - page({ - path: '/services/{serviceName}/logs', - tab: 'logs', - title: i18n.translate('xpack.apm.views.logs.title', { - defaultMessage: 'Logs', + '/services/{serviceName}/service-map': page({ + tab: 'service-map', + title: i18n.translate('xpack.apm.views.serviceMap.title', { + defaultMessage: 'Service Map', + }), + element: , + searchBarOptions: { + hidden: true, + }, }), - element: , - searchBarOptions: { - showKueryBar: false, - }, - }), - page({ - path: '/services/{serviceName}/profiling', - tab: 'profiling', - title: i18n.translate('xpack.apm.views.serviceProfiling.title', { - defaultMessage: 'Profiling', + '/services/{serviceName}/logs': page({ + tab: 'logs', + title: i18n.translate('xpack.apm.views.logs.title', { + defaultMessage: 'Logs', + }), + element: , + searchBarOptions: { + showKueryBar: false, + }, }), - element: , - }), - page({ - path: '/services/{serviceName}/infra', - tab: 'infra', - title: i18n.translate('xpack.apm.views.infra.title', { - defaultMessage: 'Infrastructure', + '/services/{serviceName}/profiling': page({ + tab: 'profiling', + title: i18n.translate('xpack.apm.views.serviceProfiling.title', { + defaultMessage: 'Profiling', + }), + element: , + }), + '/services/{serviceName}/infra': page({ + tab: 'infra', + title: i18n.translate('xpack.apm.views.infra.title', { + defaultMessage: 'Infrastructure', + }), + element: , + searchBarOptions: { + hidden: true, + }, }), - element: , - searchBarOptions: { - hidden: true, + '/services/{serviceName}/': { + element: , }, - }), - { - path: '/services/{serviceName}/', - element: , }, - ], -} as const; + }, +}; diff --git a/x-pack/plugins/apm/public/components/routing/settings/index.tsx b/x-pack/plugins/apm/public/components/routing/settings/index.tsx index afeef9c496d25..97748f2ce13ba 100644 --- a/x-pack/plugins/apm/public/components/routing/settings/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/settings/index.tsx @@ -21,129 +21,120 @@ import { Schema } from '../../app/Settings/schema'; import { AnomalyDetection } from '../../app/Settings/anomaly_detection'; import { AgentKeys } from '../../app/Settings/agent_keys'; -function page({ - path, +function page({ title, tab, element, }: { - path: TPath; title: string; tab: React.ComponentProps['selectedTab']; element: React.ReactElement; }): { element: React.ReactElement; - path: TPath; } { return { - path, element: ( - + {element} ), - } as any; + }; } export const settings = { - path: '/settings', - element: ( - - - - ), - children: [ - page({ - path: '/settings/agent-configuration', - tab: 'agent-configurations', - title: i18n.translate( - 'xpack.apm.views.settings.agentConfiguration.title', - { defaultMessage: 'Agent Configuration' } - ), - element: , - }), - { - ...page({ - path: '/settings/agent-configuration/create', + '/settings': { + element: ( + + + + ), + children: { + '/settings/agent-configuration': page({ + tab: 'agent-configuration', title: i18n.translate( - 'xpack.apm.views.settings.createAgentConfiguration.title', - { defaultMessage: 'Create Agent Configuration' } + 'xpack.apm.views.settings.agentConfiguration.title', + { defaultMessage: 'Agent Configuration' } ), - tab: 'agent-configurations', - element: , + element: , }), - params: t.partial({ - query: t.partial({ - pageStep: agentConfigurationPageStepRt, + '/settings/agent-configuration/create': { + ...page({ + title: i18n.translate( + 'xpack.apm.views.settings.createAgentConfiguration.title', + { defaultMessage: 'Create Agent Configuration' } + ), + tab: 'agent-configuration', + element: , }), - }), - }, - { - ...page({ - path: '/settings/agent-configuration/edit', - title: i18n.translate( - 'xpack.apm.views.settings.editAgentConfiguration.title', - { defaultMessage: 'Edit Agent Configuration' } - ), - tab: 'agent-configurations', - element: , - }), - params: t.partial({ - query: t.partial({ - environment: t.string, - name: t.string, - pageStep: agentConfigurationPageStepRt, + params: t.partial({ + query: t.partial({ + pageStep: agentConfigurationPageStepRt, + }), }), + }, + '/settings/agent-configuration/edit': { + ...page({ + title: i18n.translate( + 'xpack.apm.views.settings.editAgentConfiguration.title', + { defaultMessage: 'Edit Agent Configuration' } + ), + tab: 'agent-configuration', + element: , + }), + params: t.partial({ + query: t.partial({ + environment: t.string, + name: t.string, + pageStep: agentConfigurationPageStepRt, + }), + }), + }, + '/settings/apm-indices': page({ + title: i18n.translate('xpack.apm.views.settings.indices.title', { + defaultMessage: 'Indices', + }), + tab: 'apm-indices', + element: , }), - }, - page({ - path: '/settings/apm-indices', - title: i18n.translate('xpack.apm.views.settings.indices.title', { - defaultMessage: 'Indices', - }), - tab: 'apm-indices', - element: , - }), - page({ - path: '/settings/custom-links', - title: i18n.translate('xpack.apm.views.settings.customLink.title', { - defaultMessage: 'Custom Links', + '/settings/custom-links': page({ + title: i18n.translate('xpack.apm.views.settings.customLink.title', { + defaultMessage: 'Custom Links', + }), + tab: 'custom-links', + element: , }), - tab: 'custom-links', - element: , - }), - page({ - path: '/settings/schema', - title: i18n.translate('xpack.apm.views.settings.schema.title', { - defaultMessage: 'Schema', + '/settings/schema': page({ + title: i18n.translate('xpack.apm.views.settings.schema.title', { + defaultMessage: 'Schema', + }), + element: , + tab: 'schema', }), - element: , - tab: 'schema', - }), - page({ - path: '/settings/anomaly-detection', - title: i18n.translate('xpack.apm.views.settings.anomalyDetection.title', { - defaultMessage: 'Anomaly detection', + '/settings/anomaly-detection': page({ + title: i18n.translate( + 'xpack.apm.views.settings.anomalyDetection.title', + { + defaultMessage: 'Anomaly detection', + } + ), + element: , + tab: 'anomaly-detection', }), - element: , - tab: 'anomaly-detection', - }), - page({ - path: '/settings/agent-keys', - title: i18n.translate('xpack.apm.views.settings.agentKeys.title', { - defaultMessage: 'Agent keys', + '/settings/agent-keys': page({ + title: i18n.translate('xpack.apm.views.settings.agentKeys.title', { + defaultMessage: 'Agent keys', + }), + element: , + tab: 'agent-keys', }), - element: , - tab: 'agent-keys', - }), - { - path: '/settings', - element: , + '/settings': { + element: , + }, }, - ], -} as const; + }, +}; diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx index 4fc35bf242a40..a1a5e38bdd2ea 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx @@ -71,5 +71,5 @@ export const Example: Story = (args) => { }; Example.args = { children: <>test, - selectedTab: 'agent-configurations', + selectedTab: 'agent-configuration', }; diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx index 43a865c0584c9..08cacc38e89f0 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx @@ -17,7 +17,7 @@ import { getLegacyApmHref } from '../../shared/links/apm/apm_link'; type Tab = NonNullable[0] & { key: - | 'agent-configurations' + | 'agent-configuration' | 'agent-keys' | 'anomaly-detection' | 'apm-indices' @@ -66,7 +66,7 @@ function getTabs({ const tabs: Tab[] = [ { - key: 'agent-configurations', + key: 'agent-configuration', label: i18n.translate('xpack.apm.settings.agentConfig', { defaultMessage: 'Agent Configuration', }), diff --git a/x-pack/plugins/apm/public/hooks/use_apm_params.ts b/x-pack/plugins/apm/public/hooks/use_apm_params.ts index b4c17c1b329ae..89aca1e4bf1a6 100644 --- a/x-pack/plugins/apm/public/hooks/use_apm_params.ts +++ b/x-pack/plugins/apm/public/hooks/use_apm_params.ts @@ -16,17 +16,17 @@ export function useMaybeApmParams>( path: TPath, optional: true ): TypeOf | undefined { - return useParams(path, optional); + return useParams(path, optional) as TypeOf | undefined; } export function useApmParams>( path: TPath ): TypeOf { - return useParams(path)!; + return useParams(path)! as TypeOf; } export function useAnyOfApmParams>>( ...paths: TPaths ): TypeOf> { - return useParams(...paths)!; + return useParams(...paths)! as TypeOf>; } diff --git a/x-pack/plugins/apm/public/hooks/use_apm_router.ts b/x-pack/plugins/apm/public/hooks/use_apm_router.ts index dea66d7b2e1c8..d10b6da857802 100644 --- a/x-pack/plugins/apm/public/hooks/use_apm_router.ts +++ b/x-pack/plugins/apm/public/hooks/use_apm_router.ts @@ -14,8 +14,6 @@ export function useApmRouter() { const { core } = useApmPluginContext(); const link = (...args: [any]) => { - // @ts-expect-error router.link() expects never type, because - // no routes are specified. that's okay. return core.http.basePath.prepend('/app/apm' + router.link(...args)); }; diff --git a/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.test.ts b/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.test.ts index 371652cdab957..c2391967f1cd2 100644 --- a/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.test.ts +++ b/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; +import { jsonRt } from '@kbn/io-ts-utils'; import { createServerRouteRepository } from '@kbn/server-route-repository'; import { ServerRoute } from '@kbn/server-route-repository'; import * as t from 'io-ts'; diff --git a/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.ts b/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.ts index a7a4356923655..e84f97c70691b 100644 --- a/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.ts +++ b/x-pack/plugins/apm/server/routes/apm_routes/register_apm_server_routes.ts @@ -17,8 +17,7 @@ import { parseEndpoint, routeValidationObject, } from '@kbn/server-route-repository'; -import { mergeRt } from '@kbn/io-ts-utils/merge_rt'; -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; +import { jsonRt, mergeRt } from '@kbn/io-ts-utils'; import { pickKeys } from '../../../common/utils/pick_keys'; import { APMRouteHandlerResources, TelemetryUsageCounter } from '../typings'; import type { ApmPluginRequestHandlerContext } from '../typings'; diff --git a/x-pack/plugins/apm/server/routes/backends/route.ts b/x-pack/plugins/apm/server/routes/backends/route.ts index 58160477994bd..4f8d404fc529f 100644 --- a/x-pack/plugins/apm/server/routes/backends/route.ts +++ b/x-pack/plugins/apm/server/routes/backends/route.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { setupRequest } from '../../lib/helpers/setup_request'; import { environmentRt, diff --git a/x-pack/plugins/apm/server/routes/correlations/route.ts b/x-pack/plugins/apm/server/routes/correlations/route.ts index 377fedf9d1813..af267cd7294eb 100644 --- a/x-pack/plugins/apm/server/routes/correlations/route.ts +++ b/x-pack/plugins/apm/server/routes/correlations/route.ts @@ -9,7 +9,7 @@ import * as t from 'io-ts'; import Boom from '@hapi/boom'; import { i18n } from '@kbn/i18n'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { isActivePlatinumLicense } from '../../../common/license_check'; diff --git a/x-pack/plugins/apm/server/routes/default_api_types.ts b/x-pack/plugins/apm/server/routes/default_api_types.ts index b31de8e53dad2..5622b12e1b099 100644 --- a/x-pack/plugins/apm/server/routes/default_api_types.ts +++ b/x-pack/plugins/apm/server/routes/default_api_types.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { isoToEpochRt } from '@kbn/io-ts-utils/iso_to_epoch_rt'; +import { isoToEpochRt } from '@kbn/io-ts-utils'; export { environmentRt } from '../../common/environment_rt'; diff --git a/x-pack/plugins/apm/server/routes/errors/route.ts b/x-pack/plugins/apm/server/routes/errors/route.ts index f4e5ac172d5b0..2ead97f74d373 100644 --- a/x-pack/plugins/apm/server/routes/errors/route.ts +++ b/x-pack/plugins/apm/server/routes/errors/route.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; +import { jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { getErrorDistribution } from './distribution/get_distribution'; diff --git a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts index f30e98dd8c7b8..675429df9df3f 100644 --- a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts +++ b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { getOverallLatencyDistribution } from './get_overall_latency_distribution'; import { setupRequest } from '../../lib/helpers/setup_request'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; diff --git a/x-pack/plugins/apm/server/routes/observability_overview/route.ts b/x-pack/plugins/apm/server/routes/observability_overview/route.ts index c99586638c3de..b94fcf2f32a02 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview/route.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/route.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getServiceCount } from './get_service_count'; import { getTransactionsPerMinute } from './get_transactions_per_minute'; diff --git a/x-pack/plugins/apm/server/routes/rum_client/route.ts b/x-pack/plugins/apm/server/routes/rum_client/route.ts index 482dcc0799ed0..1b1b87f5d1198 100644 --- a/x-pack/plugins/apm/server/routes/rum_client/route.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/route.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; import { Logger } from 'kibana/server'; -import { isoToEpochRt } from '@kbn/io-ts-utils/iso_to_epoch_rt'; +import { isoToEpochRt } from '@kbn/io-ts-utils'; import { setupRequest, Setup } from '../../lib/helpers/setup_request'; import { getClientMetrics } from './get_client_metrics'; import { getJSErrors } from './get_js_errors'; diff --git a/x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap index a774da4e96169..df1b3954cfe29 100644 --- a/x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap @@ -187,6 +187,7 @@ Array [ "apm": Object { "events": Array [ "metric", + "error", ], }, "body": Object { diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_error_and_metric_documents.ts similarity index 92% rename from x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_services_from_error_and_metric_documents.ts index 055d82a807815..f57c02c6be806 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_error_and_metric_documents.ts @@ -16,7 +16,7 @@ import { environmentQuery } from '../../../../common/utils/environment_query'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup } from '../../../lib/helpers/setup_request'; -export async function getServicesFromMetricDocuments({ +export async function getServicesFromErrorAndMetricDocuments({ environment, setup, maxNumServices, @@ -34,10 +34,10 @@ export async function getServicesFromMetricDocuments({ const { apmEventClient } = setup; const response = await apmEventClient.search( - 'get_services_from_metric_documents', + 'get_services_from_error_and_metric_documents', { apm: { - events: [ProcessorEvent.metric], + events: [ProcessorEvent.metric, ProcessorEvent.error], }, body: { size: 0, diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts index db3377b6710c5..716fd82aefd46 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts @@ -9,7 +9,7 @@ import { Logger } from '@kbn/logging'; import { withApmSpan } from '../../../utils/with_apm_span'; import { Setup } from '../../../lib/helpers/setup_request'; import { getHealthStatuses } from './get_health_statuses'; -import { getServicesFromMetricDocuments } from './get_services_from_metric_documents'; +import { getServicesFromErrorAndMetricDocuments } from './get_services_from_error_and_metric_documents'; import { getServiceTransactionStats } from './get_service_transaction_stats'; import { mergeServiceStats } from './merge_service_stats'; @@ -45,19 +45,22 @@ export async function getServicesItems({ end, }; - const [transactionStats, servicesFromMetricDocuments, healthStatuses] = - await Promise.all([ - getServiceTransactionStats(params), - getServicesFromMetricDocuments(params), - getHealthStatuses(params).catch((err) => { - logger.error(err); - return []; - }), - ]); + const [ + transactionStats, + servicesFromErrorAndMetricDocuments, + healthStatuses, + ] = await Promise.all([ + getServiceTransactionStats(params), + getServicesFromErrorAndMetricDocuments(params), + getHealthStatuses(params).catch((err) => { + logger.error(err); + return []; + }), + ]); return mergeServiceStats({ transactionStats, - servicesFromMetricDocuments, + servicesFromErrorAndMetricDocuments, healthStatuses, }); }); diff --git a/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts index 2f5f494f3fab6..2ab94507e6a33 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts @@ -40,7 +40,7 @@ describe('mergeServiceStats', () => { throughput: 4, }), ], - servicesFromMetricDocuments: [ + servicesFromErrorAndMetricDocuments: [ { environments: ['production'], serviceName: 'opbeans-java', @@ -86,7 +86,7 @@ describe('mergeServiceStats', () => { environments: ['staging'], }), ], - servicesFromMetricDocuments: [ + servicesFromErrorAndMetricDocuments: [ { environments: ['production'], serviceName: 'opbeans-java', @@ -128,7 +128,7 @@ describe('mergeServiceStats', () => { environments: ['staging'], }), ], - servicesFromMetricDocuments: [], + servicesFromErrorAndMetricDocuments: [], healthStatuses: [ { healthStatus: ServiceHealthStatus.healthy, @@ -158,7 +158,7 @@ describe('mergeServiceStats', () => { environments: ['staging'], }), ], - servicesFromMetricDocuments: [ + servicesFromErrorAndMetricDocuments: [ { environments: ['production'], serviceName: 'opbeans-java', diff --git a/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts index aad9d095edc4f..1a0c91f83dbf1 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts @@ -8,17 +8,17 @@ import { uniq } from 'lodash'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; import { joinByKey } from '../../../../common/utils/join_by_key'; import { getHealthStatuses } from './get_health_statuses'; -import { getServicesFromMetricDocuments } from './get_services_from_metric_documents'; +import { getServicesFromErrorAndMetricDocuments } from './get_services_from_error_and_metric_documents'; import { getServiceTransactionStats } from './get_service_transaction_stats'; export function mergeServiceStats({ transactionStats, - servicesFromMetricDocuments, + servicesFromErrorAndMetricDocuments, healthStatuses, }: { transactionStats: Awaited>; - servicesFromMetricDocuments: Awaited< - ReturnType + servicesFromErrorAndMetricDocuments: Awaited< + ReturnType >; healthStatuses: Awaited>; }) { @@ -26,9 +26,10 @@ export function mergeServiceStats({ ({ serviceName }) => serviceName ); - const servicesWithOnlyMetricDocuments = servicesFromMetricDocuments.filter( - ({ serviceName }) => !foundServiceNames.includes(serviceName) - ); + const servicesWithOnlyMetricDocuments = + servicesFromErrorAndMetricDocuments.filter( + ({ serviceName }) => !foundServiceNames.includes(serviceName) + ); const allServiceNames = foundServiceNames.concat( servicesWithOnlyMetricDocuments.map(({ serviceName }) => serviceName) @@ -43,7 +44,7 @@ export function mergeServiceStats({ return joinByKey( asMutableArray([ ...transactionStats, - ...servicesFromMetricDocuments, + ...servicesFromErrorAndMetricDocuments, ...matchedHealthStatuses, ] as const), 'serviceName', diff --git a/x-pack/plugins/apm/server/routes/services/route.ts b/x-pack/plugins/apm/server/routes/services/route.ts index 2b7a71ba13acf..de5f457f18dec 100644 --- a/x-pack/plugins/apm/server/routes/services/route.ts +++ b/x-pack/plugins/apm/server/routes/services/route.ts @@ -6,9 +6,7 @@ */ import Boom from '@hapi/boom'; -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; -import { isoToEpochRt } from '@kbn/io-ts-utils/iso_to_epoch_rt'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { isoToEpochRt, jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { uniq } from 'lodash'; import { latencyAggregationTypeRt } from '../../../common/latency_aggregation_types'; diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts index 26a9eaefc0413..b8245a8efaa94 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts @@ -7,7 +7,7 @@ import * as t from 'io-ts'; import Boom from '@hapi/boom'; -import { toBooleanRt } from '@kbn/io-ts-utils/to_boolean_rt'; +import { toBooleanRt } from '@kbn/io-ts-utils'; import { maxSuggestions } from '../../../../../observability/common'; import { setupRequest } from '../../../lib/helpers/setup_request'; import { getServiceNames } from './get_service_names'; diff --git a/x-pack/plugins/apm/server/routes/source_maps/route.ts b/x-pack/plugins/apm/server/routes/source_maps/route.ts index b0b7eb5134fcf..a60c59c03589d 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/route.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/route.ts @@ -7,7 +7,7 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; import { SavedObjectsClientContract } from 'kibana/server'; -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; +import { jsonRt } from '@kbn/io-ts-utils'; import { createApmArtifact, deleteApmArtifact, diff --git a/x-pack/plugins/apm/server/routes/transactions/route.ts b/x-pack/plugins/apm/server/routes/transactions/route.ts index cad1c3b8f353b..49c50f5a9100d 100644 --- a/x-pack/plugins/apm/server/routes/transactions/route.ts +++ b/x-pack/plugins/apm/server/routes/transactions/route.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { jsonRt } from '@kbn/io-ts-utils/json_rt'; -import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; +import { jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { LatencyAggregationType, diff --git a/x-pack/plugins/data_visualizer/common/index.ts b/x-pack/plugins/data_visualizer/common/index.ts deleted file mode 100644 index 58159dfc3d7ef..0000000000000 --- a/x-pack/plugins/data_visualizer/common/index.ts +++ /dev/null @@ -1,12 +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. - */ - -// TODO: https://github.com/elastic/kibana/issues/110898 -/* eslint-disable @kbn/eslint/no_export_all */ - -export * from './constants'; -export * from './types'; diff --git a/x-pack/plugins/data_visualizer/kibana.json b/x-pack/plugins/data_visualizer/kibana.json index 9687a896c2c41..ea6f338ca07d0 100644 --- a/x-pack/plugins/data_visualizer/kibana.json +++ b/x-pack/plugins/data_visualizer/kibana.json @@ -30,9 +30,6 @@ "fieldFormats", "uiActions" ], - "extraPublicDirs": [ - "common" - ], "owner": { "name": "Machine Learning UI", "githubTeam": "ml-ui" diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx index 7ba1615e22b43..07e5d01e71d9b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx @@ -16,7 +16,7 @@ import { NumberContent, } from '../stats_table/components/field_data_expanded_row'; import { GeoPointContent } from './geo_point_content/geo_point_content'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; import type { FileBasedFieldVisConfig } from '../../../../../common/types/field_vis_config'; export const FileBasedDataVisualizerExpandedRow = ({ item }: { item: FileBasedFieldVisConfig }) => { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx index 5da44262d29da..0c1c02ec033b2 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx @@ -13,7 +13,7 @@ import { DocumentStatsTable } from '../../stats_table/components/field_data_expa import { ExamplesList } from '../../examples_list'; import { FieldVisConfig } from '../../stats_table/types'; import { useDataVisualizerKibana } from '../../../../kibana_context'; -import { JOB_FIELD_TYPES } from '../../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; import { ES_GEO_FIELD_TYPE, LayerDescriptor } from '../../../../../../../maps/common'; import { EmbeddedMapComponent } from '../../embedded_map'; import { ExpandedRowPanel } from '../../stats_table/components/field_data_expanded_row/expanded_row_panel'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx index b87da2b3da789..dd82fb4df33b8 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { GeoPointContentWithMap } from './geo_point_content_with_map'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; import { BooleanContent, DateContent, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts index 831cf8aab02a9..34023691307d0 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts @@ -17,7 +17,7 @@ import { dataVisualizerRefresh$, Refresh, } from '../../../../index_data_visualizer/services/timefilter_refresh_service'; -import { JOB_FIELD_TYPES } from '../../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../../../../../../src/plugins/ui_actions/public'; export function getActions( diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts index 70aa103b86d53..3db1795456127 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts @@ -18,7 +18,7 @@ import type { XYLayerConfig, } from '../../../../../../../lens/public'; import { FieldVisConfig } from '../../stats_table/types'; -import { JOB_FIELD_TYPES } from '../../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; interface ColumnsAndLayer { columns: Record; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx index 0c036dd6c6d76..874cdaa670c49 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { FieldTypeIcon } from './field_type_icon'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; describe('FieldTypeIcon', () => { test(`render component when type matches a field type`, () => { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx index 8699523057510..ea24ba91cf7f2 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx @@ -10,7 +10,7 @@ import { EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FieldIcon } from '@kbn/react-field'; import { getJobTypeLabel } from '../../util/field_types_utils'; -import type { JobFieldType } from '../../../../../common'; +import type { JobFieldType } from '../../../../../common/types'; import './_index.scss'; interface FieldTypeIconProps { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts index f80ccd42919e2..26002f0404c44 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts @@ -8,7 +8,7 @@ import { FindFileStructureResponse } from '../../../../../../file_upload/common'; import { getFieldNames, getSupportedFieldType } from './get_field_names'; import { FileBasedFieldVisConfig } from '../stats_table/types'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; import { roundToDecimalPlace } from '../utils'; export function createFields(results: FindFileStructureResponse) { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx index 1173ede84e631..dae5c6524d168 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx @@ -8,7 +8,7 @@ import React, { useMemo, FC, useState } from 'react'; import { EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import type { FindFileStructureResponse } from '../../../../../../file_upload/common'; -import type { DataVisualizerTableState } from '../../../../../common'; +import type { DataVisualizerTableState } from '../../../../../common/types'; import { DataVisualizerTable, ItemIdToExpandedRowMap } from '../stats_table'; import type { FileBasedFieldVisConfig } from '../../../../../common/types/field_vis_config'; import { FileBasedDataVisualizerExpandedRow } from '../expanded_row'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts index 9f1ea4af22537..de97b6007d877 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; import type { FileBasedFieldVisConfig, FileBasedUnknownFieldVisConfig, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts index 6ca6421bbd124..8ac53aaf3b3a7 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts @@ -8,8 +8,8 @@ import { difference } from 'lodash'; import { ES_FIELD_TYPES } from '../../../../../../../../src/plugins/data/common'; import type { FindFileStructureResponse } from '../../../../../../file_upload/common'; -import type { JobFieldType } from '../../../../../common'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import type { JobFieldType } from '../../../../../common/types'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; export function getFieldNames(results: FindFileStructureResponse) { const { mappings, field_stats: fieldStats, column_names: columnNames } = results; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx index 976afc464a672..34b40e73571ba 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx @@ -23,7 +23,8 @@ import { import { i18n } from '@kbn/i18n'; import { EuiTableComputedColumnType } from '@elastic/eui/src/components/basic_table/table_types'; import { throttle } from 'lodash'; -import { JOB_FIELD_TYPES, JobFieldType, DataVisualizerTableState } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import type { JobFieldType, DataVisualizerTableState } from '../../../../../common/types'; import { DocumentStat } from './components/field_data_row/document_stats'; import { IndexBasedNumberContentPreview } from './components/field_data_row/number_content_preview'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts index 87d936edc2957..778aaa3697c7b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts @@ -8,7 +8,7 @@ import { Direction, EuiBasicTableProps, Pagination, PropertySort } from '@elastic/eui'; import { useCallback, useMemo } from 'react'; -import { DataVisualizerTableState } from '../../../../../common'; +import type { DataVisualizerTableState } from '../../../../../common/types'; const PAGE_SIZE_OPTIONS = [10, 25, 50, 100]; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts index 5f9317be6d7c5..fdac866c286c2 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/utils/utils.ts @@ -7,7 +7,7 @@ import { isEqual } from 'lodash'; import type { AnalysisResult, InputOverrides } from '../../../../../../file_upload/common'; -import { MB, FILE_FORMATS } from '../../../../../common'; +import { MB, FILE_FORMATS } from '../../../../../common/constants'; export const DEFAULT_LINES_TO_SAMPLE = 1000; const UPLOAD_SIZE_MB = 5; diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts index 710ba12313f17..8f9e4ffd3b898 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { JOB_FIELD_TYPES } from '../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../common/constants'; import { getJobTypeLabel, jobTypeLabels } from './field_types_utils'; describe('field type utils', () => { diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts index 1fda7140dbab2..33931ea74b4ea 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { JOB_FIELD_TYPES } from '../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../common/constants'; import type { IndexPatternField } from '../../../../../../../src/plugins/data/common'; import { KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/common'; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx index b754bfd4691ec..b0bd51e1b9a39 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/analysis_summary/analysis_summary.tsx @@ -10,7 +10,7 @@ import React, { FC } from 'react'; import { EuiTitle, EuiSpacer, EuiDescriptionList } from '@elastic/eui'; import type { FindFileStructureResponse } from '../../../../../../file_upload/common'; -import { FILE_FORMATS } from '../../../../../common'; +import { FILE_FORMATS } from '../../../../../common/constants'; export const AnalysisSummary: FC<{ results: FindFileStructureResponse }> = ({ results }) => { const items = createDisplayItems(results); diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/options/options.ts b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/options/options.ts index e0c3e7f2d58cc..8ff3de07cc81a 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/options/options.ts +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/options/options.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FILE_FORMATS } from '../../../../../../common/'; +import { FILE_FORMATS } from '../../../../../../common/constants'; import { TIMESTAMP_OPTIONS, diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.js index d0213813c8f16..9fbed83136f8f 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.js @@ -23,7 +23,7 @@ import { EuiTextArea, } from '@elastic/eui'; -import { FILE_FORMATS } from '../../../../../common'; +import { FILE_FORMATS } from '../../../../../common/constants'; import { getFormatOptions, diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.test.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.test.js index 8e9b0d0806fc1..8a4695f823128 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.test.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/edit_flyout/overrides.test.js @@ -7,7 +7,7 @@ import { mountWithIntl, shallowWithIntl } from '@kbn/test/jest'; import React from 'react'; -import { FILE_FORMATS } from '../../../../../common'; +import { FILE_FORMATS } from '../../../../../common/constants'; import { Overrides } from './overrides'; diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx index 9daac8604d661..c2c0910098a18 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_error_callouts.tsx @@ -11,7 +11,7 @@ import React, { FC } from 'react'; import { EuiCallOut, EuiSpacer, EuiButtonEmpty, EuiHorizontalRule } from '@elastic/eui'; import numeral from '@elastic/numeral'; -import { FILE_SIZE_DISPLAY_FORMAT } from '../../../../../common'; +import { FILE_SIZE_DISPLAY_FORMAT } from '../../../../../common/constants'; import { FindFileStructureErrorResponse } from '../../../../../../file_upload/common'; interface FileTooLargeProps { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index 1c988869526b1..bbee06ef85c34 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -39,7 +39,7 @@ import { JobFieldType, SavedSearchSavedObject } from '../../../../../common/type import { useDataVisualizerKibana } from '../../../kibana_context'; import { FieldCountPanel } from '../../../common/components/field_count_panel'; import { DocumentCountContent } from '../../../common/components/document_count_content'; -import { OMIT_FIELDS } from '../../../../../common'; +import { OMIT_FIELDS } from '../../../../../common/constants'; import { kbnTypeToJobType } from '../../../common/util/field_types_utils'; import { SearchPanel } from '../search_panel'; import { ActionsPanel } from '../actions_panel'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx index ee54683b08435..0bf61865f30c6 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx @@ -8,7 +8,7 @@ import React, { FC, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { JobFieldType } from '../../../../../common'; +import type { JobFieldType } from '../../../../../common/types'; import { FieldTypeIcon } from '../../../common/components/field_type_icon'; import { MultiSelectPicker, Option } from '../../../common/components/multi_select_picker'; import { jobTypeLabels } from '../../../common/util/field_types_utils'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx index 2ce6670dfafef..e1757690e8963 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx @@ -39,7 +39,7 @@ import { } from '../../../common/components/stats_table'; import { FieldVisConfig } from '../../../common/components/stats_table/types'; import { getDefaultDataVisualizerListState } from '../../components/index_data_visualizer_view/index_data_visualizer_view'; -import { DataVisualizerTableState, SavedSearchSavedObject } from '../../../../../common'; +import type { DataVisualizerTableState, SavedSearchSavedObject } from '../../../../../common/types'; import { DataVisualizerIndexBasedAppState } from '../../types/index_data_visualizer_state'; import { IndexBasedDataVisualizerExpandedRow } from '../../../common/components/expanded_row/index_based_expanded_row'; import { useDataVisualizerGridData } from '../../hooks/use_data_visualizer_grid_data'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts index 1b209c28fdf56..1895b22fe8288 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts @@ -24,12 +24,11 @@ import { } from '../../../../../../../src/plugins/data/common'; import { FieldVisConfig } from '../../common/components/stats_table/types'; import { - FieldRequestConfig, JOB_FIELD_TYPES, - JobFieldType, NON_AGGREGATABLE_FIELD_TYPES, OMIT_FIELDS, -} from '../../../../common'; +} from '../../../../common/constants'; +import type { FieldRequestConfig, JobFieldType } from '../../../../common/types'; import { kbnTypeToJobType } from '../../common/util/field_types_utils'; import { getActions } from '../../common/components/field_data_row/action_menu'; import { DataVisualizerGridInput } from '../embeddables/grid_embeddable/grid_embeddable'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_field_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_field_stats.ts index 64654d56db05b..bd60fec47b598 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_field_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_field_stats.ts @@ -18,7 +18,7 @@ import type { Field, } from '../../../../common/types/field_stats'; import { useDataVisualizerKibana } from '../../kibana_context'; -import type { FieldRequestConfig } from '../../../../common'; +import type { FieldRequestConfig } from '../../../../common/types'; import type { DataVisualizerIndexBasedAppState } from '../types/index_data_visualizer_state'; import { buildBaseFilterCriteria, diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts index aa19aa9fbb495..747d4007ac1ff 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts @@ -11,7 +11,7 @@ import type { FieldStatsError } from '../../../../../common/types/field_stats'; import type { ISearchOptions } from '../../../../../../../../src/plugins/data/common'; import { ISearchStart } from '../../../../../../../../src/plugins/data/public'; import type { FieldStats } from '../../../../../common/types/field_stats'; -import { JOB_FIELD_TYPES } from '../../../../../common'; +import { JOB_FIELD_TYPES } from '../../../../../common/constants'; import { fetchDateFieldsStats } from './get_date_field_stats'; import { fetchBooleanFieldsStats } from './get_boolean_field_stats'; import { fetchFieldsExamples } from './get_field_examples'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts index 60be59ab2db6c..6b72e8c09d600 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts @@ -10,7 +10,7 @@ import { createMergedEsQuery, getEsQueryFromSavedSearch, } from './saved_search_utils'; -import type { SavedSearchSavedObject } from '../../../../common'; +import type { SavedSearchSavedObject } from '../../../../common/types'; import type { SavedSearch } from '../../../../../../../src/plugins/discover/public'; import type { Filter, FilterStateStore } from '@kbn/es-query'; import { stubbedSavedObjectIndexPattern } from '../../../../../../../src/plugins/data_views/common/data_view.stub'; diff --git a/x-pack/plugins/data_visualizer/public/register_home.ts b/x-pack/plugins/data_visualizer/public/register_home.ts index 9338c93000ec9..0619382bd994c 100644 --- a/x-pack/plugins/data_visualizer/public/register_home.ts +++ b/x-pack/plugins/data_visualizer/public/register_home.ts @@ -9,7 +9,12 @@ import { i18n } from '@kbn/i18n'; import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public'; import { FileDataVisualizerWrapper } from './lazy_load_bundle/component_wrapper'; -import { featureTitle, FILE_DATA_VIS_TAB_ID, applicationPath, featureId } from '../common'; +import { + featureTitle, + FILE_DATA_VIS_TAB_ID, + applicationPath, + featureId, +} from '../common/constants'; export function registerHomeAddData(home: HomePublicPluginSetup) { home.addData.registerAddDataTab({ diff --git a/x-pack/plugins/data_visualizer/server/register_custom_integration.ts b/x-pack/plugins/data_visualizer/server/register_custom_integration.ts index 67be78277189b..5ff58c5ed4d90 100644 --- a/x-pack/plugins/data_visualizer/server/register_custom_integration.ts +++ b/x-pack/plugins/data_visualizer/server/register_custom_integration.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { CustomIntegrationsPluginSetup } from '../../../../src/plugins/custom_integrations/server'; -import { applicationPath, featureId, featureTitle } from '../common'; +import { applicationPath, featureId, featureTitle } from '../common/constants'; export function registerWithCustomIntegrations(customIntegrations: CustomIntegrationsPluginSetup) { customIntegrations.registerCustomIntegration({ diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index 6eb31fd79aa77..fe34b36f7781f 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -34,6 +34,7 @@ export interface FleetConfigType { agentIdVerificationEnabled?: boolean; developer?: { disableRegistryVersionCheck?: boolean; + allowAgentUpgradeSourceUri?: boolean; }; } diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index f66bf00a5a054..7bf3ca161f4ee 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -96,6 +96,7 @@ export const config: PluginConfigDescriptor = { agentIdVerificationEnabled: schema.boolean({ defaultValue: true }), developer: schema.object({ disableRegistryVersionCheck: schema.boolean({ defaultValue: false }), + allowAgentUpgradeSourceUri: schema.boolean({ defaultValue: false }), }), }), }; diff --git a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts index 52f62037f61e6..bf386e7f463a7 100644 --- a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts @@ -28,6 +28,7 @@ export const postAgentUpgradeHandler: RequestHandler< const kibanaVersion = appContextService.getKibanaVersion(); try { checkVersionIsSame(version, kibanaVersion); + checkSourceUriAllowed(sourceUri); } catch (err) { return response.customError({ statusCode: 400, @@ -82,6 +83,7 @@ export const postBulkAgentsUpgradeHandler: RequestHandler< const kibanaVersion = appContextService.getKibanaVersion(); try { checkVersionIsSame(version, kibanaVersion); + checkSourceUriAllowed(sourceUri); } catch (err) { return response.customError({ statusCode: 400, @@ -127,3 +129,11 @@ export const checkVersionIsSame = (version: string, kibanaVersion: string) => { `cannot upgrade agent to ${versionToUpgradeNumber} because it is different than the installed kibana version ${kibanaVersionNumber}` ); }; + +const checkSourceUriAllowed = (sourceUri?: string) => { + if (sourceUri && !appContextService.getConfig()?.developer?.allowAgentUpgradeSourceUri) { + throw new Error( + `source_uri is not allowed or recommended in production. Set xpack.fleet.developer.allowAgentUpgradeSourceUri in kibana.yml to enable.` + ); + } +}; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 4bbbb355d573e..a8289d5766cc5 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -51,6 +51,7 @@ const initialRuleState: TestRuleState = { const mockOptions = { alertId: '', + executionId: '', startedAt: new Date(), previousStartedAt: null, state: { diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index 73a25f36e22bd..ff45c996cce98 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -186,9 +186,8 @@ export async function mountApp( embeddableEditorIncomingState, initialContext, }; - const emptyState = getPreloadedState(storeDeps) as LensAppState; const lensStore: LensRootStore = makeConfigureStore(storeDeps, { - lens: emptyState, + lens: getPreloadedState(storeDeps) as LensAppState, } as PreloadedState); const EditorRenderer = React.memo( @@ -208,7 +207,7 @@ export async function mountApp( if (!initialContext) { data.query.filterManager.setAppFilters([]); } - lensStore.dispatch(setState(emptyState)); + lensStore.dispatch(setState(getPreloadedState(storeDeps) as LensAppState)); lensStore.dispatch(loadInitial({ redirectCallback, initialInput, history: props.history })); return ( diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index a3b6638d5ee8b..af2d1577834b7 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -403,7 +403,7 @@ export class MapEmbeddable render( - {content}; + {content} , this._domNode diff --git a/x-pack/plugins/observability/common/utils/formatters/duration.test.ts b/x-pack/plugins/observability/common/utils/formatters/duration.test.ts index eaf073cfbb5b3..69f4792325a35 100644 --- a/x-pack/plugins/observability/common/utils/formatters/duration.test.ts +++ b/x-pack/plugins/observability/common/utils/formatters/duration.test.ts @@ -71,7 +71,7 @@ describe('duration formatters', () => { [1000, '1,000.0 tpm'], [1000000, '1,000,000.0 tpm'], ])( - 'displays the correct label when the number is integer and has zero decimals', + 'displays the correct label when the number is a positive integer and has zero decimals', (value, formattedValue) => { expect(asTransactionRate(value)).toBe(formattedValue); } @@ -89,12 +89,39 @@ describe('duration formatters', () => { expect(asTransactionRate(value)).toBe(formattedValue); } ); + + it.each([ + [-1, '< 0.1 tpm'], + [-10, '< 0.1 tpm'], + [-100, '< 0.1 tpm'], + [-1000, '< 0.1 tpm'], + [-1000000, '< 0.1 tpm'], + ])( + 'displays the correct label when the number is a negative integer and has zero decimals', + (value, formattedValue) => { + expect(asTransactionRate(value)).toBe(formattedValue); + } + ); + + it.each([ + [-1.23, '< 0.1 tpm'], + [-12.34, '< 0.1 tpm'], + [-123.45, '< 0.1 tpm'], + [-1234.56, '< 0.1 tpm'], + [-1234567.89, '< 0.1 tpm'], + ])( + 'displays the correct label when the number is negative and has decimal part', + (value, formattedValue) => { + expect(asTransactionRate(value)).toBe(formattedValue); + } + ); }); describe('asMilliseconds', () => { it('converts to formatted decimal milliseconds', () => { expect(asMillisecondDuration(0)).toEqual('0 ms'); }); + it('formats correctly with undefined values', () => { expect(asMillisecondDuration(undefined)).toEqual('N/A'); }); diff --git a/x-pack/plugins/observability/common/utils/formatters/formatters.test.ts b/x-pack/plugins/observability/common/utils/formatters/formatters.test.ts index c3b65ce7699d0..397eaae04b51a 100644 --- a/x-pack/plugins/observability/common/utils/formatters/formatters.test.ts +++ b/x-pack/plugins/observability/common/utils/formatters/formatters.test.ts @@ -108,5 +108,29 @@ describe('formatters', () => { ])('formats as decimal when number is below 10 ', (value, formattedValue) => { expect(asDecimalOrInteger(value)).toBe(formattedValue); }); + + it.each([ + [-0.123, '-0.1'], + [-1.234, '-1.2'], + [-9.876, '-9.9'], + ])( + 'formats as decimal when number is negative and below 10 in absolute value', + (value, formattedValue) => { + expect(asDecimalOrInteger(value)).toEqual(formattedValue); + } + ); + + it.each([ + [-12.34, '-12'], + [-123.45, '-123'], + [-1234.56, '-1,235'], + [-12345.67, '-12,346'], + [-12345678.9, '-12,345,679'], + ])( + 'formats as integer when number is negative and above or equals 10 in absolute value', + (value, formattedValue) => { + expect(asDecimalOrInteger(value)).toEqual(formattedValue); + } + ); }); }); diff --git a/x-pack/plugins/observability/common/utils/formatters/formatters.ts b/x-pack/plugins/observability/common/utils/formatters/formatters.ts index 9bdccc7e9edfe..05d8d2638ba7b 100644 --- a/x-pack/plugins/observability/common/utils/formatters/formatters.ts +++ b/x-pack/plugins/observability/common/utils/formatters/formatters.ts @@ -51,7 +51,7 @@ export type AsPercent = typeof asPercent; export function asDecimalOrInteger(value: number) { // exact 0 or above 10 should not have decimal - if (value === 0 || value >= 10) { + if (value === 0 || Math.abs(value) >= 10) { return asInteger(value); } return asDecimal(value); diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts index d0feac5f8aa32..c81329baad572 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts @@ -107,6 +107,11 @@ export const technicalRuleFieldMap = { array: false, required: false, }, + [Fields.ALERT_RULE_EXECUTION_UUID]: { + type: 'keyword', + array: false, + required: false, + }, [Fields.ALERT_RULE_FROM]: { type: 'keyword', array: false, diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts index d822d9316ad19..05a71677c7535 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts @@ -119,6 +119,7 @@ function createRule(shouldWriteAlerts: boolean = true) { tags: ['tags'], updatedBy: 'updatedBy', namespace: 'namespace', + executionId: 'b33f65d7-6e8b-4aae-8d20-c93613dec9f9', })) ?? {}) as Record; previousStartedAt = startedAt; @@ -224,6 +225,7 @@ describe('createLifecycleRuleTypeFactory', () => { "kibana.alert.instance.id": "opbeans-java", "kibana.alert.rule.category": "ruleTypeName", "kibana.alert.rule.consumer": "consumer", + "kibana.alert.rule.execution.uuid": "b33f65d7-6e8b-4aae-8d20-c93613dec9f9", "kibana.alert.rule.name": "name", "kibana.alert.rule.producer": "producer", "kibana.alert.rule.rule_type_id": "ruleTypeId", @@ -251,6 +253,7 @@ describe('createLifecycleRuleTypeFactory', () => { "kibana.alert.instance.id": "opbeans-node", "kibana.alert.rule.category": "ruleTypeName", "kibana.alert.rule.consumer": "consumer", + "kibana.alert.rule.execution.uuid": "b33f65d7-6e8b-4aae-8d20-c93613dec9f9", "kibana.alert.rule.name": "name", "kibana.alert.rule.producer": "producer", "kibana.alert.rule.rule_type_id": "ruleTypeId", diff --git a/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts b/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts index 8b4daf30763f6..db8c56f84b2c4 100644 --- a/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts +++ b/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts @@ -11,6 +11,7 @@ import { ALERT_UUID, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAME, ALERT_RULE_PRODUCER, ALERT_RULE_TYPE_ID, @@ -26,6 +27,7 @@ import { ParsedTechnicalFields } from '../../common/parse_technical_fields'; const commonAlertFieldNames = [ ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAME, ALERT_RULE_PRODUCER, ALERT_RULE_TYPE_ID, @@ -47,6 +49,7 @@ export const getCommonAlertFields = ( return { [ALERT_RULE_CATEGORY]: options.rule.ruleTypeName, [ALERT_RULE_CONSUMER]: options.rule.consumer, + [ALERT_RULE_EXECUTION_UUID]: options.executionId, [ALERT_RULE_NAME]: options.rule.name, [ALERT_RULE_PRODUCER]: options.rule.producer, [ALERT_RULE_TYPE_ID]: options.rule.ruleTypeId, diff --git a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts index 10cce043fe3fd..08b1b0a8ecbf2 100644 --- a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts +++ b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts @@ -79,4 +79,5 @@ export const createDefaultAlertExecutorOptions = < updatedBy: null, previousStartedAt: null, namespace: undefined, + executionId: 'b33f65d7-6e8b-4aae-8d20-c93613deb33f', }); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts index 7b9dd63c73251..964819164b315 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts @@ -57,7 +57,7 @@ describe('Alert details with unmapped fields', () => { // This test needs to be updated to not look for the field in a specific row, as it prevents us from adding/removing fields it.skip('Displays the unmapped field on the table', () => { const expectedUnmmappedField = { - row: 82, + row: 83, field: 'unmapped', text: 'This is the unmapped field', }; diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx index db2af21d4e325..30f62c7637974 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx @@ -88,7 +88,13 @@ export const getHostsColumns = (showRiskColumn: boolean): HostsTableColumns => { }, { field: 'node.host.os.name', - name: i18n.OS, + name: ( + + <> + {i18n.OS} + + + ), truncateText: false, mobileOptions: { show: true }, sortable: false, diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/translations.ts b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/translations.ts index 88c01f695b940..ead534b1edc5b 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/translations.ts +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/translations.ts @@ -40,6 +40,13 @@ export const HOST_RISK_TOOLTIP = i18n.translate( } ); +export const OS_LAST_SEEN_TOOLTIP = i18n.translate( + 'xpack.securitySolution.hostsTable.osLastSeenToolTip', + { + defaultMessage: 'Most recently observed OS', + } +); + export const OS = i18n.translate('xpack.securitySolution.hostsTable.osTitle', { defaultMessage: 'Operating system', }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts index f064380cc4a13..1d97b7a39779a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts @@ -39,6 +39,7 @@ describe('legacyRules_notification_alert_type', () => { payload = { alertId: '1111', + executionId: 'b33f65d7-b33f-4aae-8d20-c93613dec9f9', services: alertServices, params: { ruleAlertId: '2222' }, state: {}, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap index e03e438650df9..b826ed83d34ed 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap @@ -4164,6 +4164,13 @@ Object { "enabled": Object { "type": "keyword", }, + "execution": Object { + "properties": Object { + "uuid": Object { + "type": "keyword", + }, + }, + }, "false_positives": Object { "type": "keyword", }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json index 4f754ecd2d33a..6df246d06760d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json @@ -286,6 +286,13 @@ "enabled": { "type": "keyword" }, + "execution": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, "filters": { "type": "object" }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts index 204c67bf6cf5a..263aa9e54737d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts @@ -170,6 +170,7 @@ export const previewRulesRoute = async ( statePreview = (await executor({ alertId: previewId, createdBy: rule.createdBy, + executionId: uuid.v4(), name: rule.name, params, previousStartedAt, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts index 22a41f356c226..7cf82722c47ff 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts @@ -23,6 +23,7 @@ const ruleExecutionLogClientMock = { const ruleExecutionLoggerMock = { create: (context: Partial = {}): jest.Mocked => ({ context: { + executionId: context.executionId ?? 'some execution id', ruleId: context.ruleId ?? 'some rule id', ruleName: context.ruleName ?? 'Some rule', ruleType: context.ruleType ?? 'some rule type', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts index dad30e9cb5d88..2869f1c2c82e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts @@ -24,6 +24,7 @@ export interface IRuleExecutionEventsWriter { } export interface BaseArgs { + executionId: string; ruleId: string; ruleName: string; ruleType: string; @@ -49,7 +50,7 @@ export const createRuleExecutionEventsWriter = ( let sequence = 0; return { - logStatusChange({ ruleId, ruleName, ruleType, spaceId, newStatus, message }) { + logStatusChange({ executionId, ruleId, ruleName, ruleType, spaceId, newStatus, message }) { eventLogger.logEvent({ '@timestamp': nowISO(), message, @@ -69,6 +70,7 @@ export const createRuleExecutionEventsWriter = ( execution: { status: newStatus, status_order: ruleExecutionStatusOrderByStatus[newStatus], + uuid: executionId, }, }, }, @@ -85,7 +87,7 @@ export const createRuleExecutionEventsWriter = ( }); }, - logExecutionMetrics({ ruleId, ruleName, ruleType, spaceId, metrics }) { + logExecutionMetrics({ executionId, ruleId, ruleName, ruleType, spaceId, metrics }) { eventLogger.logEvent({ '@timestamp': nowISO(), rule: { @@ -103,6 +105,7 @@ export const createRuleExecutionEventsWriter = ( rule: { execution: { metrics, + uuid: executionId, }, }, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts index f67aae472ef60..a3e14f9569e25 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts @@ -28,7 +28,7 @@ export const createRuleExecutionLogger = ( logger: Logger, context: RuleExecutionContext ): IRuleExecutionLogger => { - const { ruleId, ruleName, ruleType, spaceId } = context; + const { executionId, ruleId, ruleName, ruleType, spaceId } = context; const ruleExecutionLogger: IRuleExecutionLogger = { get context() { @@ -44,7 +44,7 @@ export const createRuleExecutionLogger = ( ]); } catch (e) { const logMessage = 'Error logging rule execution status change'; - const logAttributes = `status: "${args.newStatus}", rule id: "${ruleId}", rule name: "${ruleName}"`; + const logAttributes = `status: "${args.newStatus}", rule id: "${ruleId}", rule name: "${ruleName}", execution uuid: "${executionId}"`; const logReason = e instanceof Error ? e.stack ?? e.message : String(e); const logMeta: ExtMeta = { rule: { @@ -53,6 +53,7 @@ export const createRuleExecutionLogger = ( type: ruleType, execution: { status: args.newStatus, + uuid: executionId, }, }, kibana: { @@ -65,6 +66,7 @@ export const createRuleExecutionLogger = ( }, }; + // TODO: Add executionId to new status SO? const writeStatusChangeToSavedObjects = async ( args: NormalizedStatusChangeArgs ): Promise => { @@ -86,6 +88,7 @@ export const createRuleExecutionLogger = ( if (metrics) { eventsWriter.logExecutionMetrics({ + executionId, ruleId, ruleName, ruleType, @@ -95,6 +98,7 @@ export const createRuleExecutionLogger = ( } eventsWriter.logStatusChange({ + executionId, ruleId, ruleName, ruleType, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts index e31c10bd9747f..874d60cf4a401 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts @@ -29,6 +29,7 @@ export interface IRuleExecutionLogger { } export interface RuleExecutionContext { + executionId: string; ruleId: string; ruleName: string; ruleType: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts index a643f428e58e7..ba30b0335fb39 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts @@ -60,6 +60,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = return withSecuritySpan('scurityRuleTypeExecutor', async () => { const { alertId, + executionId, params, previousStartedAt, startedAt, @@ -81,6 +82,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = eventLogService, logger, { + executionId, ruleId: alertId, ruleName: rule.name, ruleType: rule.ruleTypeId, @@ -104,6 +106,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = const buildRuleMessage = buildRuleMessageFactory({ id: alertId, + executionId, ruleId, name, index: spaceId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts index 6ebc902db6992..bac112bb3cab1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts @@ -7,6 +7,7 @@ export type BuildRuleMessage = (...messages: string[]) => string; export interface BuildRuleMessageFactoryParams { + executionId: string; name: string; id: string; ruleId: string | null | undefined; @@ -15,12 +16,13 @@ export interface BuildRuleMessageFactoryParams { // TODO: change `index` param to `spaceId` export const buildRuleMessageFactory = - ({ id, ruleId, index, name }: BuildRuleMessageFactoryParams): BuildRuleMessage => + ({ executionId, id, ruleId, index, name }: BuildRuleMessageFactoryParams): BuildRuleMessage => (...messages) => [ ...messages, `name: "${name}"`, `id: "${id}"`, `rule id: "${ruleId ?? '(unknown rule id)'}"`, + `execution id: "${executionId}"`, `space ID: "${index}"`, ].join(' '); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts index 88b4ae01b3a64..07f2dfa31015c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts @@ -93,6 +93,8 @@ export const buildAncestors = (doc: SimpleHit): Ancestor[] => { * Builds the `kibana.alert.*` fields that are common across all alerts. * @param docs The parent alerts/events of the new alert to be built. * @param rule The rule that is generating the new alert. + * @param spaceId The space ID in which the rule was executed. + * @param reason Human readable string summarizing alert. */ export const buildAlert = ( docs: SimpleHit[], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index c620d51a83382..cae1019ae3f80 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -663,7 +663,6 @@ describe('utils', () => { }, }, }; - const ruleExecutionLogger = ruleExecutionLogMock.logger.create(); mockLogger.warn.mockClear(); diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts index de769686dc99c..22e1e9329ca2c 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts @@ -18,7 +18,7 @@ describe('Snapshot serialization and deserialization', () => { repository: 'repositoryName', version_id: 5, version: 'version', - indices: ['index2', 'index3', 'index1'], + indices: ['index2', 'index3', 'index1', '.kibana'], include_global_state: false, state: 'SUCCESS', start_time: '0', @@ -31,6 +31,12 @@ describe('Snapshot serialization and deserialization', () => { failed: 1, successful: 2, }, + feature_states: [ + { + feature_name: 'kibana', + indices: ['.kibana'], + }, + ], failures: [ { index: 'z', @@ -71,6 +77,12 @@ describe('Snapshot serialization and deserialization', () => { failed: 1, successful: 2, }, + feature_states: [ + { + feature_name: 'kibana', + indices: ['.kibana'], + }, + ], failures: [ { index: 'z', @@ -98,7 +110,7 @@ describe('Snapshot serialization and deserialization', () => { uuid: 'UUID', versionId: 5, version: 'version', - // Indices are sorted. + // Indices are sorted and dont include any of the system indices listed in feature_state indices: ['index1', 'index2', 'index3'], dataStreams: [], includeGlobalState: false, diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index f2803a571c475..e6e047cfa5d7d 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -6,6 +6,7 @@ */ import { sortBy } from 'lodash'; +import { flow, map, flatten, uniq } from 'lodash/fp'; import { SnapshotDetails, @@ -20,6 +21,19 @@ import { deserializeTime, serializeTime } from './time_serialization'; import { csvToArray } from './utils'; +export const convertFeaturesToIndicesArray = ( + features: SnapshotDetailsEs['feature_states'] +): string[] => { + return flow( + // Map each feature into Indices[] + map('indices'), + // Flatten the array + flatten, + // And finally dedupe the indices + uniq + )(features); +}; + export function deserializeSnapshotDetails( snapshotDetailsEs: SnapshotDetailsEs, managedRepository?: string, @@ -46,21 +60,27 @@ export function deserializeSnapshotDetails( duration_in_millis: durationInMillis, failures = [], shards, + feature_states: featureStates = [], metadata: { policy: policyName } = { policy: undefined }, } = snapshotDetailsEs; + const systemIndices = convertFeaturesToIndicesArray(featureStates); + const snapshotIndicesWithoutSystemIndices = indices + .filter((index) => !systemIndices.includes(index)) + .sort(); + // If an index has multiple failures, we'll want to see them grouped together. - const indexToFailuresMap = failures.reduce((map, failure) => { + const indexToFailuresMap = failures.reduce((aggregation, failure) => { const { index, ...rest } = failure; - if (!map[index]) { - map[index] = { + if (!aggregation[index]) { + aggregation[index] = { index, failures: [], }; } - map[index].failures.push(rest); - return map; + aggregation[index].failures.push(rest); + return aggregation; }, {}); // Sort all failures by their shard. @@ -80,7 +100,7 @@ export function deserializeSnapshotDetails( uuid, versionId, version, - indices: [...indices].sort(), + indices: snapshotIndicesWithoutSystemIndices, dataStreams: [...dataStreams].sort(), includeGlobalState, state, diff --git a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts index 97f3b00d97326..baddcac7f5094 100644 --- a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts @@ -68,6 +68,10 @@ export interface SnapshotDetailsEs { duration_in_millis: number; failures: any[]; shards: SnapshotDetailsShardsStatusEs; + feature_states: Array<{ + feature_name: string; + indices: string[]; + }>; metadata?: { policy: string; [key: string]: any; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts index 6b424adaa54ab..c0d05c44201fb 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts @@ -140,6 +140,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -218,6 +219,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -369,6 +371,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -446,6 +449,7 @@ describe('alertType', () => { const executorOptions = { alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -559,6 +563,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -642,6 +647,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts index 7ab382ec77172..f6b1c4a3a3b0a 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts @@ -169,6 +169,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices<{}, ActionContext, typeof ActionGroupId>, @@ -230,6 +231,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: customAlertServices as unknown as AlertServices< @@ -295,6 +297,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: customAlertServices as unknown as AlertServices< diff --git a/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts b/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts index a4cc9d5139148..3ee7929170338 100644 --- a/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts +++ b/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts @@ -16,7 +16,7 @@ interface EqualCondition { equal: number; } -function isEqualConsition( +function isEqualCondition( condition: GreaterThanEqualCondition | EqualCondition ): condition is EqualCondition { return Number.isInteger((condition as EqualCondition).equal); @@ -67,7 +67,7 @@ export async function getEventLog(params: GetEventLogParams): Promise= condition.gte) ) @@ -76,7 +76,7 @@ export async function getEventLog(params: GetEventLogParams): Promise event?.event?.action !== 'execute' ); + // Verify unique executionId generated per `action:execute` grouping + const eventExecutionIdSet = new Set(); + const totalUniqueExecutionIds = new Set(); + let totalExecutionEventCount = 0; + events.forEach((event) => { + totalUniqueExecutionIds.add(event?.kibana?.alert?.rule?.execution?.uuid); + if (event?.event?.action === 'execute') { + totalExecutionEventCount += 1; + eventExecutionIdSet.add(event?.kibana?.alert?.rule?.execution?.uuid); + expect(eventExecutionIdSet.size).to.equal(1); + eventExecutionIdSet.clear(); + } else { + eventExecutionIdSet.add(event?.kibana?.alert?.rule?.execution?.uuid); + } + }); + + // Ensure every execution actually had a unique id from the others + expect(totalUniqueExecutionIds.size).to.equal(totalExecutionEventCount); + const currentAlertSpan: { alertId?: string; start?: string; diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts index 17f9e28a91c3e..9d56eb312ee5c 100644 --- a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts @@ -64,6 +64,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const transactionInterval = range.interval('1s'); const metricInterval = range.interval('30s'); + const errorInterval = range.interval('5s'); + const multipleEnvServiceProdInstance = apm .service('multiple-env-service', 'production', 'go') .instance('multiple-env-service-production'); @@ -76,6 +78,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .service('metric-only-service', 'production', 'java') .instance('metric-only-production'); + const errorOnlyInstance = apm + .service('error-only-service', 'production', 'java') + .instance('error-only-production'); + const config = { multiple: { prod: { @@ -132,6 +138,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { .timestamp(timestamp) .serialize(), ]), + ...errorInterval + .rate(1) + .flatMap((timestamp) => [ + ...errorOnlyInstance.error('Foo').timestamp(timestamp).serialize(), + ]), ]); }); @@ -185,6 +196,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const serviceNames = response.body.items.map((item) => item.serviceName); expect(serviceNames).to.contain('metric-only-service'); + + expect(serviceNames).to.contain('error-only-service'); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts index cb1c41852465f..343db03c2ae27 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { ALERT_REASON, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAMESPACE, ALERT_RULE_PARAMETERS, ALERT_RULE_UPDATED_AT, @@ -120,6 +121,7 @@ export default ({ getService }: FtrProviderContext) => { expect(signal._source).eql({ '@timestamp': signal._source['@timestamp'], + [ALERT_RULE_EXECUTION_UUID]: signal._source[ALERT_RULE_EXECUTION_UUID], [ALERT_UUID]: signal._source[ALERT_UUID], [VERSION]: signal._source[VERSION], actual: [1], diff --git a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts index 8708b035050cc..8901c3166ca14 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts @@ -57,7 +57,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ version: kibanaVersion, - source_uri: 'http://path/to/download', }) .expect(200); @@ -160,9 +159,23 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ version: higherVersion, + }) + .expect(400); + }); + it('should respond 400 if trying to upgrade with source_uri set', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const res = await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, source_uri: 'http://path/to/download', }) .expect(400); + + expect(res.body.message).to.eql( + `source_uri is not allowed or recommended in production. Set xpack.fleet.developer.allowAgentUpgradeSourceUri in kibana.yml to enable.` + ); }); it('should respond 400 if trying to upgrade an agent that is unenrolling', async () => { const kibanaVersion = await kibanaServer.version.get(); @@ -545,6 +558,43 @@ export default function (providerContext: FtrProviderContext) { .expect(400); }); + it('should respond 400 if trying to bulk upgrade to a version that does not match installed kibana version', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + const res = await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2'], + version: kibanaVersion, + source_uri: 'http://path/to/download', + force: true, + }) + .expect(400); + expect(res.body.message).to.eql( + `source_uri is not allowed or recommended in production. Set xpack.fleet.developer.allowAgentUpgradeSourceUri in kibana.yml to enable.` + ); + }); + it('enrolled in a hosted agent policy bulk upgrade should respond with 200 and object of results. Should not update the hosted agent SOs', async () => { // move agent2 to policy2 to keep it regular await supertest.put(`/api/fleet/agents/agent2/reassign`).set('kbn-xsrf', 'xxx').send({ diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts index ac36bad1f595b..be3146f34c30e 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts @@ -9,6 +9,7 @@ import expect from '@kbn/expect'; import { ALERT_DURATION, ALERT_END, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_UUID, ALERT_START, ALERT_STATUS, @@ -187,7 +188,14 @@ export default function registryRulesApiTest({ getService }: FtrProviderContext) const alertEvent = afterViolatingDataResponse.hits.hits[0].fields as Record; - const exclude = ['@timestamp', ALERT_START, ALERT_UUID, ALERT_RULE_UUID, VERSION]; + const exclude = [ + '@timestamp', + ALERT_START, + ALERT_UUID, + ALERT_RULE_EXECUTION_UUID, + ALERT_RULE_UUID, + VERSION, + ]; const toCompare = omit(alertEvent, exclude); diff --git a/yarn.lock b/yarn.lock index 2e4d6ddc987fb..e3d2628f89f34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5864,6 +5864,10 @@ version "0.0.0" uid "" +"@types/kbn__io-ts-utils@link:bazel-bin/packages/kbn-io-ts-utils/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__mapbox-gl@link:bazel-bin/packages/kbn-mapbox-gl/npm_module_types": version "0.0.0" uid "" @@ -20430,10 +20434,10 @@ node-fetch@2.6.1, node-fetch@^1.0.1, node-fetch@^2.3.0, node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-forge@^0.10.0, node-forge@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.1.0.tgz#53e61b039eea78b442a4e13f9439dbd61b5cd3a8" - integrity sha512-HeZMFB41cirRysIhIFFgORmR51/qhkjRTXXIH9QiwS3AjF9L9Kre9XvOnyE7NMubOSHDuN0GsrFpnqhlJcNWTA== +node-forge@^0.10.0, node-forge@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" + integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== node-gyp-build@^4.2.3: version "4.2.3"