From dbde0a75f92303b525d7845735085d08329006a1 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Fri, 3 Dec 2021 15:43:32 -0500 Subject: [PATCH 01/35] Update performance docs to touch on server-side considerations (#120356) * Update performance docs to touch on server-side considerations * update edited date --- dev_docs/key_concepts/performance.mdx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dev_docs/key_concepts/performance.mdx b/dev_docs/key_concepts/performance.mdx index 0201c7774f854..5d955c789ddeb 100644 --- a/dev_docs/key_concepts/performance.mdx +++ b/dev_docs/key_concepts/performance.mdx @@ -3,11 +3,13 @@ id: kibDevPerformance slug: /kibana-dev-docs/key-concepts/performance title: Performance summary: Performance tips for Kibana development. -date: 2021-09-02 +date: 2021-12-03 tags: ['kibana', 'onboarding', 'dev', 'performance'] --- -## Keep Kibana fast +## Client-side considerations + +### Lazy load code _tl;dr_: Load as much code lazily as possible. Everyone loves snappy applications with a responsive UI and hates spinners. Users deserve the @@ -105,3 +107,15 @@ Many OSS tools allow you to analyze the generated stats file: Webpack authors - [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/) - [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) + +## Server-side considerations + +### Don't block the event loop + +[Node.js is single threaded](https://nodejs.dev/learn/introduction-to-nodejs) which means a single CPU-intensive server-side, synchronous operation will block any other functionality waiting to execute on the Kibana server. The affects background tasks, like alerts, and search sessions, as well as search requests and page loads. + +**When writing code that will run on the server, [don't block the event loop](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/)**. Instead consider: + +- Writing async code. For example, leverage [setImmediate](https://nodejs.dev/learn/understanding-setimmediate) inside for loops. +- Executing logic on the client instead. This may not be a good option if you require a lot of data going back and forth between the server and the client, as that can also slow down the user's experience, especially over slower bandwidth internet connections. +- Worker threads are also an option if the code doesn't rely on stateful Kibana services. If you are interested in using worker threads, please reach out to a tech-lead before doing so. We will likely want to implement a worker threads pool to ensure worker threads cooperate appropriately. \ No newline at end of file From d21d721bd1104a3e231baa5775fcc6749423aafa Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Fri, 3 Dec 2021 12:44:50 -0800 Subject: [PATCH 02/35] [presentation] Create Expression Input (#119411) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/presentation_util/common/index.ts | 6 + src/plugins/presentation_util/kibana.json | 13 +- .../expression_input}/autocomplete.ts | 24 +- .../components/expression_input/constants.ts | 28 ++ .../expression_input.stories.tsx | 94 +++++ .../expression_input/expression_input.tsx | 82 +++++ .../components/expression_input/index.tsx | 16 + .../components/expression_input/language.ts | 23 +- .../components/expression_input/providers.ts | 189 ++++++++++ .../components/expression_input/reference.ts | 24 +- .../public/components/index.tsx | 5 + .../public/components/types.ts | 43 +++ src/plugins/presentation_util/public/index.ts | 19 +- src/plugins/presentation_util/public/mocks.ts | 2 + .../presentation_util/public/plugin.ts | 3 + .../public/services/index.ts | 3 + src/plugins/presentation_util/public/types.ts | 2 + .../presentation_util/storybook/decorator.tsx | 20 +- .../presentation_util/storybook/main.ts | 4 +- .../presentation_util/storybook/manager.ts | 5 + .../canvas/common/lib/autocomplete.test.ts | 198 ---------- x-pack/plugins/canvas/common/lib/index.ts | 1 - x-pack/plugins/canvas/public/application.tsx | 3 - .../components/expression/expression.tsx | 19 +- .../public/components/expression/index.tsx | 7 +- .../expression_input.stories.storyshot | 33 +- .../__stories__/expression_input.stories.tsx | 76 ++-- .../expression_input/expression_input.tsx | 344 ++---------------- x-pack/plugins/canvas/public/plugin.tsx | 5 + .../canvas/storybook/storyshots.test.tsx | 5 + .../translations/translations/ja-JP.json | 12 +- .../translations/translations/zh-CN.json | 12 +- 32 files changed, 663 insertions(+), 657 deletions(-) rename {x-pack/plugins/canvas/common/lib => src/plugins/presentation_util/public/components/expression_input}/autocomplete.ts (98%) create mode 100644 src/plugins/presentation_util/public/components/expression_input/constants.ts create mode 100644 src/plugins/presentation_util/public/components/expression_input/expression_input.stories.tsx create mode 100644 src/plugins/presentation_util/public/components/expression_input/expression_input.tsx create mode 100644 src/plugins/presentation_util/public/components/expression_input/index.tsx rename x-pack/plugins/canvas/public/lib/monaco_language_def.ts => src/plugins/presentation_util/public/components/expression_input/language.ts (74%) create mode 100644 src/plugins/presentation_util/public/components/expression_input/providers.ts rename {x-pack/plugins/canvas => src/plugins/presentation_util}/public/components/expression_input/reference.ts (79%) delete mode 100644 x-pack/plugins/canvas/common/lib/autocomplete.test.ts diff --git a/src/plugins/presentation_util/common/index.ts b/src/plugins/presentation_util/common/index.ts index 4510a0aac5a0b..a84a78c823a5f 100644 --- a/src/plugins/presentation_util/common/index.ts +++ b/src/plugins/presentation_util/common/index.ts @@ -12,4 +12,10 @@ export const PLUGIN_ID = 'presentationUtil'; export const PLUGIN_NAME = 'presentationUtil'; +/** + * The unique identifier for the Expressions Language for use in the ExpressionInput + * and CodeEditor components. + */ +export const EXPRESSIONS_LANGUAGE_ID = 'kibana-expressions'; + export * from './labs'; diff --git a/src/plugins/presentation_util/kibana.json b/src/plugins/presentation_util/kibana.json index 210937b335e50..32460a8455152 100644 --- a/src/plugins/presentation_util/kibana.json +++ b/src/plugins/presentation_util/kibana.json @@ -9,7 +9,16 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "extraPublicDirs": ["common/lib"], - "requiredPlugins": ["savedObjects", "data", "dataViews", "embeddable", "kibanaReact"], + "extraPublicDirs": [ + "common/lib" + ], + "requiredPlugins": [ + "savedObjects", + "data", + "dataViews", + "embeddable", + "kibanaReact", + "expressions" + ], "optionalPlugins": [] } diff --git a/x-pack/plugins/canvas/common/lib/autocomplete.ts b/src/plugins/presentation_util/public/components/expression_input/autocomplete.ts similarity index 98% rename from x-pack/plugins/canvas/common/lib/autocomplete.ts rename to src/plugins/presentation_util/public/components/expression_input/autocomplete.ts index 88fb6b052b957..5f0c9cab6215c 100644 --- a/x-pack/plugins/canvas/common/lib/autocomplete.ts +++ b/src/plugins/presentation_util/public/components/expression_input/autocomplete.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 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 { uniq } from 'lodash'; @@ -15,9 +16,9 @@ import { ExpressionFunction, ExpressionFunctionParameter, getByAlias, -} from '../../../../../src/plugins/expressions/common'; +} from '../../../../expressions/common'; -const MARKER = 'CANVAS_SUGGESTION_MARKER'; +const MARKER = 'EXPRESSIONS_SUGGESTION_MARKER'; interface BaseSuggestion { text: string; @@ -25,11 +26,6 @@ interface BaseSuggestion { end: number; } -export interface FunctionSuggestion extends BaseSuggestion { - type: 'function'; - fnDef: ExpressionFunction; -} - interface ArgSuggestionValue extends Omit { name: string; } @@ -43,8 +39,6 @@ interface ValueSuggestion extends BaseSuggestion { type: 'value'; } -export type AutocompleteSuggestion = FunctionSuggestion | ArgSuggestion | ValueSuggestion; - interface FnArgAtPosition { ast: ExpressionASTWithMeta; fnIndex: number; @@ -57,6 +51,7 @@ interface FnArgAtPosition { // If this function is a sub-expression function, we need the parent function and argument // name to determine the return type of the function parentFn?: string; + // If this function is a sub-expression function, the context could either be local or it // could be the parent's previous function. contextFn?: string | null; @@ -101,6 +96,13 @@ type ExpressionASTWithMeta = ASTMetaInformation< > >; +export interface FunctionSuggestion extends BaseSuggestion { + type: 'function'; + fnDef: ExpressionFunction; +} + +export type AutocompleteSuggestion = FunctionSuggestion | ArgSuggestion | ValueSuggestion; + // Typeguard for checking if ExpressionArg is a new expression function isExpression( maybeExpression: ExpressionArgASTWithMeta diff --git a/src/plugins/presentation_util/public/components/expression_input/constants.ts b/src/plugins/presentation_util/public/components/expression_input/constants.ts new file mode 100644 index 0000000000000..f937d55cbf9bb --- /dev/null +++ b/src/plugins/presentation_util/public/components/expression_input/constants.ts @@ -0,0 +1,28 @@ +/* + * 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 { CodeEditorProps } from '../../../../kibana_react/public'; + +export const LANGUAGE_CONFIGURATION = { + autoClosingPairs: [ + { + open: '{', + close: '}', + }, + ], +}; + +export const CODE_EDITOR_OPTIONS: CodeEditorProps['options'] = { + scrollBeyondLastLine: false, + quickSuggestions: true, + minimap: { + enabled: false, + }, + wordWrap: 'on', + wrappingIndent: 'indent', +}; diff --git a/src/plugins/presentation_util/public/components/expression_input/expression_input.stories.tsx b/src/plugins/presentation_util/public/components/expression_input/expression_input.stories.tsx new file mode 100644 index 0000000000000..648171959791f --- /dev/null +++ b/src/plugins/presentation_util/public/components/expression_input/expression_input.stories.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { Meta } from '@storybook/react'; + +import { ExpressionFunction, ExpressionFunctionParameter, Style } from 'src/plugins/expressions'; +import { ExpressionInput } from '../expression_input'; +import { registerExpressionsLanguage } from './language'; + +const content: ExpressionFunctionParameter<'string'> = { + name: 'content', + required: false, + help: 'A string of text that contains Markdown. To concatenate, pass the `string` function multiple times.', + types: ['string'], + default: '', + aliases: ['_', 'expression'], + multi: true, + resolve: false, + options: [], + accepts: () => true, +}; + +const font: ExpressionFunctionParameter