diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b783c76b76e..6e957b3fc27 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -323,6 +323,7 @@ /packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend /packages/grafana-data/src/**/*logs* @grafana/observability-logs /packages/grafana-schema/src/**/*tempo* @grafana/observability-traces-and-profiling +/packages/grafana-flamegraph/ @grafana/observability-traces-and-profiling /plugins-bundled/ @grafana/plugins-platform-frontend diff --git a/package.json b/package.json index 43cacb56df7..09abd2e163a 100644 --- a/package.json +++ b/package.json @@ -248,6 +248,7 @@ "@grafana/experimental": "1.7.0", "@grafana/faro-core": "1.1.2", "@grafana/faro-web-sdk": "1.1.2", + "@grafana/flamegraph": "workspace:*", "@grafana/google-sdk": "0.1.1", "@grafana/lezer-logql": "0.1.11", "@grafana/lezer-traceql": "0.0.5", diff --git a/packages/grafana-flamegraph/.eslintrc b/packages/grafana-flamegraph/.eslintrc new file mode 100644 index 00000000000..0dbc8077ffc --- /dev/null +++ b/packages/grafana-flamegraph/.eslintrc @@ -0,0 +1,19 @@ +{ + "rules": { + "no-restricted-imports": [ + "error", + { + "patterns": ["@grafana/runtime", "@grafana/e2e", "@grafana/e2e-selectors/*"] + } + ] + }, + "overrides": [ + { + "files": ["**/*.{test,story}.{ts,tsx}"], + "rules": { + "no-restricted-imports": "off", + "react/prop-types": "off" + } + } + ] +} diff --git a/packages/grafana-flamegraph/CHANGELOG.md b/packages/grafana-flamegraph/CHANGELOG.md new file mode 100644 index 00000000000..cae66adcee5 --- /dev/null +++ b/packages/grafana-flamegraph/CHANGELOG.md @@ -0,0 +1,3 @@ +# 10.2.0 (2023-09-06) + +First public release diff --git a/packages/grafana-flamegraph/LICENSE_APACHE2 b/packages/grafana-flamegraph/LICENSE_APACHE2 new file mode 100644 index 00000000000..373dde574a0 --- /dev/null +++ b/packages/grafana-flamegraph/LICENSE_APACHE2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2015 Grafana Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/grafana-flamegraph/README.md b/packages/grafana-flamegraph/README.md new file mode 100644 index 00000000000..5a0df9974c7 --- /dev/null +++ b/packages/grafana-flamegraph/README.md @@ -0,0 +1,53 @@ +# Grafana Flamegraph component + +> **@grafana/flamegraph is currently in BETA**. + +This is a Flamegraph component that is used in Grafana and Pyroscope web app to display profiles. + +## Usage + +Currently this library exposes single component `Flamegraph` that renders whole visualization used for profiling which contains a header, a table representation of the data and a flamegraph. + +```tsx +import { Flamegraph } from '@grafana/flamegraph'; + + createTheme({ colors: { mode: 'dark' } })} + data={dataFrame} + extraHeaderElements={ + + ) : null; + + return ( +
+
+ { + setLocalSearch(v.currentTarget.value); + }} + placeholder={'Search..'} + suffix={suffix} + /> +
+ +
+ {showResetButton && ( +
+
+ ); +}; + +type ColorSchemeButtonProps = { + value: ColorScheme | ColorSchemeDiff; + onChange: (colorScheme: ColorScheme | ColorSchemeDiff) => void; + getTheme: () => GrafanaTheme2; + isDiffMode: boolean; +}; +function ColorSchemeButton(props: ColorSchemeButtonProps) { + // TODO: probably create separate getStyles + const styles = getStyles(props.getTheme(), false); + let menu = ( + + props.onChange(ColorScheme.ValueBased)} /> + props.onChange(ColorScheme.PackageBased)} /> + + ); + + if (props.isDiffMode) { + menu = ( + + props.onChange(ColorSchemeDiff.Default)} /> + props.onChange(ColorSchemeDiff.DiffColorBlind)} /> + + ); + } + + // Show a bit different gradient as a way to indicate selected value + const colorDotStyle = + { + [ColorScheme.ValueBased]: styles.colorDotByValue, + [ColorScheme.PackageBased]: styles.colorDotByPackage, + [ColorSchemeDiff.DiffColorBlind]: styles.colorDotDiffColorBlind, + [ColorSchemeDiff.Default]: styles.colorDotDiffDefault, + }[props.value] || styles.colorDotByValue; + + return ( + + + + ); +} + +const alignOptions: Array> = [ + { value: 'left', description: 'Align text left', icon: 'align-left' }, + { value: 'right', description: 'Align text right', icon: 'align-right' }, +]; + +function getViewOptions(width: number, vertical?: boolean): Array> { + let viewOptions: Array<{ value: SelectedView; label: string; description: string }> = [ + { value: SelectedView.TopTable, label: 'Top Table', description: 'Only show top table' }, + { value: SelectedView.FlameGraph, label: 'Flame Graph', description: 'Only show flame graph' }, + ]; + + if (width >= MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH || vertical) { + viewOptions.push({ + value: SelectedView.Both, + label: 'Both', + description: 'Show both the top table and flame graph', + }); + } + + return viewOptions; +} + +function useSearchInput( + search: string, + setSearch: (search: string) => void +): [string | undefined, (search: string) => void] { + const [localSearchState, setLocalSearchState] = useState(search); + const prevSearch = usePrevious(search); + + // Debouncing cause changing parent search triggers rerender on both the flamegraph and table + useDebounce( + () => { + setSearch(localSearchState); + }, + 250, + [localSearchState] + ); + + // Make sure we still handle updates from parent (from clicking on a table item for example). We check if the parent + // search value changed to something that isn't our local value. + useEffect(() => { + if (prevSearch !== search && search !== localSearchState) { + setLocalSearchState(search); + } + }, [search, prevSearch, localSearchState]); + + return [localSearchState, setLocalSearchState]; +} + +const getStyles = (theme: GrafanaTheme2, sticky?: boolean) => ({ + header: css` + label: header; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + width: 100%; + top: 0; + z-index: ${theme.zIndex.navbarFixed}; + ${sticky + ? css` + position: sticky; + padding-bottom: ${theme.spacing(1)}; + padding-top: ${theme.spacing(1)}; + background: ${theme.colors.background.primary}; + ` + : ''}; + `, + inputContainer: css` + label: inputContainer; + margin-right: 20px; + flex-grow: 1; + min-width: 150px; + max-width: 350px; + `, + rightContainer: css` + label: rightContainer; + display: flex; + align-items: flex-start; + flex-wrap: wrap; + `, + buttonSpacing: css` + label: buttonSpacing; + margin-right: ${theme.spacing(1)}; + `, + + resetButton: css` + label: resetButton; + display: flex; + margin-right: ${theme.spacing(2)}; + `, + resetButtonIconWrapper: css` + label: resetButtonIcon; + padding: 0 5px; + color: ${theme.colors.text.disabled}; + `, + colorDot: css` + label: colorDot; + display: inline-block; + width: 10px; + height: 10px; + border-radius: 50%; + `, + colorDotByValue: css` + label: colorDotByValue; + background: ${byValueGradient}; + `, + colorDotByPackage: css` + label: colorDotByPackage; + background: ${byPackageGradient}; + `, + colorDotDiffDefault: css` + label: colorDotDiffDefault; + background: ${diffDefaultGradient}; + `, + colorDotDiffColorBlind: css` + label: colorDotDiffColorBlind; + background: ${diffColorBlindGradient}; + `, + extraElements: css` + label: extraElements; + margin-left: ${theme.spacing(1)}; + `, +}); + +export default FlameGraphHeader; diff --git a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.test.tsx b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.test.tsx new file mode 100644 index 00000000000..be5f85a64ec --- /dev/null +++ b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.test.tsx @@ -0,0 +1,76 @@ +import { render, screen } from '@testing-library/react'; +import userEvents from '@testing-library/user-event'; +import React from 'react'; + +import { createDataFrame, createTheme } from '@grafana/data'; + +import { FlameGraphDataContainer } from '../FlameGraph/dataTransform'; +import { data } from '../FlameGraph/testData/dataNestedSet'; + +import FlameGraphTopTableContainer from './FlameGraphTopTableContainer'; + +describe('FlameGraphTopTableContainer', () => { + const setup = () => { + const flameGraphData = createDataFrame(data); + const container = new FlameGraphDataContainer(flameGraphData); + const onSearch = jest.fn(); + const onSandwich = jest.fn(); + + const renderResult = render( + createTheme({ colors: { mode: 'dark' } })} + /> + ); + + return { renderResult, mocks: { onSearch, onSandwich } }; + }; + + it('should render correctly', async () => { + // Needed for AutoSizer to work in test + Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, value: 500 }); + Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { configurable: true, value: 500 }); + + setup(); + const rows = screen.getAllByRole('row'); + expect(rows).toHaveLength(16); + + const columnHeaders = screen.getAllByRole('columnheader'); + expect(columnHeaders).toHaveLength(4); + expect(columnHeaders[1].textContent).toEqual('Symbol'); + expect(columnHeaders[2].textContent).toEqual('Self'); + expect(columnHeaders[3].textContent).toEqual('Total'); + + const cells = screen.getAllByRole('cell'); + expect(cells).toHaveLength(60); // 16 rows + expect(cells[1].textContent).toEqual('net/http.HandlerFunc.ServeHTTP'); + expect(cells[2].textContent).toEqual('31.7 K'); + expect(cells[3].textContent).toEqual('31.7 Bil'); + expect(cells[25].textContent).toEqual('net/http.(*conn).serve'); + expect(cells[26].textContent).toEqual('5.63 K'); + expect(cells[27].textContent).toEqual('5.63 Bil'); + }); + + it('should render search and sandwich buttons', async () => { + // Needed for AutoSizer to work in test + Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, value: 500 }); + Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { configurable: true, value: 500 }); + + const { mocks } = setup(); + + const searchButtons = screen.getAllByLabelText(/Search for symbol/); + expect(searchButtons.length > 0).toBeTruthy(); + await userEvents.click(searchButtons[0]); + + expect(mocks.onSearch).toHaveBeenCalledWith('net/http.HandlerFunc.ServeHTTP'); + + const sandwichButtons = screen.getAllByLabelText(/Show in sandwich view/); + expect(sandwichButtons.length > 0).toBeTruthy(); + await userEvents.click(sandwichButtons[0]); + + expect(mocks.onSandwich).toHaveBeenCalledWith('net/http.HandlerFunc.ServeHTTP'); + }); +}); diff --git a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx new file mode 100644 index 00000000000..e106f052e85 --- /dev/null +++ b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx @@ -0,0 +1,362 @@ +import { css } from '@emotion/css'; +import React, { useMemo, useState } from 'react'; +import AutoSizer from 'react-virtualized-auto-sizer'; + +import { + applyFieldOverrides, + DataFrame, + DataLinkClickEvent, + Field, + FieldType, + GrafanaTheme2, + MappingType, +} from '@grafana/data'; +import { + IconButton, + Table, + TableCellDisplayMode, + TableCustomCellOptions, + TableFieldOptions, + TableSortByFieldState, +} from '@grafana/ui'; + +import { FlameGraphDataContainer } from '../FlameGraph/dataTransform'; +import { TOP_TABLE_COLUMN_WIDTH } from '../constants'; +import { TableData } from '../types'; + +type Props = { + data: FlameGraphDataContainer; + onSymbolClick: (symbol: string) => void; + height?: number; + search?: string; + sandwichItem?: string; + onSearch: (str: string) => void; + onSandwich: (str?: string) => void; + onTableSort?: (sort: string) => void; + getTheme: () => GrafanaTheme2; + vertical?: boolean; +}; + +const FlameGraphTopTableContainer = React.memo( + ({ + data, + onSymbolClick, + height, + search, + onSearch, + sandwichItem, + onSandwich, + onTableSort, + getTheme, + vertical, + }: Props) => { + const table = useMemo(() => { + // Group the data by label, we show only one row per label and sum the values + // TODO: should be by filename + funcName + linenumber? + let table: { [key: string]: TableData } = {}; + for (let i = 0; i < data.data.length; i++) { + const value = data.getValue(i); + const valueRight = data.getValueRight(i); + const self = data.getSelf(i); + const label = data.getLabel(i); + table[label] = table[label] || {}; + table[label].self = table[label].self ? table[label].self + self : self; + table[label].total = table[label].total ? table[label].total + value : value; + table[label].totalRight = table[label].totalRight ? table[label].totalRight + valueRight : valueRight; + } + return table; + }, [data]); + + const rowHeight = 35; + // When we use normal layout we size the table to have the same height as the flamegraph to look good side by side. + // In vertical layout we don't need that so this is a bit arbitrary. We want some max limit + // so we don't show potentially thousands of rows at once which can hinder performance (the table is virtualized + // so with some max height it handles it fine) + const tableHeight = vertical ? Math.min(Object.keys(table).length * rowHeight, 800) : 0; + const styles = getStyles(tableHeight); + + const [sort, setSort] = useState([{ displayName: 'Self', desc: true }]); + + return ( +
+ + {({ width, height }) => { + if (width < 3 || height < 3) { + return null; + } + + const frame = buildTableDataFrame( + data, + table, + width, + onSymbolClick, + onSearch, + onSandwich, + getTheme, + search, + sandwichItem + ); + return ( + { + if (s && s.length) { + onTableSort?.(s[0].displayName + '_' + (s[0].desc ? 'desc' : 'asc')); + } + setSort(s); + }} + data={frame} + width={width} + height={height} + /> + ); + }} + + + ); + } +); + +FlameGraphTopTableContainer.displayName = 'FlameGraphTopTableContainer'; + +function buildTableDataFrame( + data: FlameGraphDataContainer, + table: { [key: string]: TableData }, + width: number, + onSymbolClick: (str: string) => void, + onSearch: (str: string) => void, + onSandwich: (str?: string) => void, + getTheme: () => GrafanaTheme2, + search?: string, + sandwichItem?: string +): DataFrame { + const actionField: Field = createActionField(onSandwich, onSearch, search, sandwichItem); + + const symbolField: Field = { + type: FieldType.string, + name: 'Symbol', + values: [], + config: { + custom: { width: width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 2 }, + links: [ + { + title: 'Highlight symbol', + url: '', + onClick: (e: DataLinkClickEvent) => { + const field: Field = e.origin.field; + const value = field.values[e.origin.rowIndex]; + onSymbolClick(value); + }, + }, + ], + }, + }; + + let frame; + + if (data.isDiffFlamegraph()) { + symbolField.config.custom.width = width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 3; + + const baselineField = createNumberField('Baseline', 'percent'); + const comparisonField = createNumberField('Comparison', 'percent'); + const diffField = createNumberField('Diff', 'percent'); + diffField.config.custom.cellOptions.type = TableCellDisplayMode.ColorText; + diffField.config.mappings = [ + { type: MappingType.ValueToText, options: { [Infinity]: { text: 'new', color: 'red' } } }, + { type: MappingType.ValueToText, options: { [-100]: { text: 'removed', color: 'green' } } }, + { type: MappingType.RangeToText, options: { from: 0, to: Infinity, result: { color: 'red' } } }, + { type: MappingType.RangeToText, options: { from: -Infinity, to: 0, result: { color: 'green' } } }, + ]; + + // For this we don't really consider sandwich view even though you can switch it on. + const levels = data.getLevels(); + const totalTicks = levels.length ? levels[0][0].value : 0; + const totalTicksRight = levels.length ? levels[0][0].valueRight : undefined; + + for (let key in table) { + actionField.values.push(null); + symbolField.values.push(key); + + const ticksLeft = table[key].total; + const ticksRight = table[key].totalRight; + + // We are iterating over table of the data so totalTicksRight needs to be defined + const totalTicksLeft = totalTicks - totalTicksRight!; + + const percentageLeft = Math.round((10000 * ticksLeft) / totalTicksLeft) / 100; + const percentageRight = Math.round((10000 * ticksRight) / totalTicksRight!) / 100; + + const diff = ((percentageRight - percentageLeft) / percentageLeft) * 100; + + diffField.values.push(diff); + baselineField.values.push(percentageLeft); + comparisonField.values.push(percentageRight); + } + + frame = { + fields: [actionField, symbolField, baselineField, comparisonField, diffField], + length: symbolField.values.length, + }; + } else { + const selfField = createNumberField('Self', data.selfField.config.unit); + const totalField = createNumberField('Total', data.valueField.config.unit); + + for (let key in table) { + actionField.values.push(null); + symbolField.values.push(key); + selfField.values.push(table[key].self); + totalField.values.push(table[key].total); + } + + frame = { fields: [actionField, symbolField, selfField, totalField], length: symbolField.values.length }; + } + + const dataFrames = applyFieldOverrides({ + data: [frame], + fieldConfig: { + defaults: {}, + overrides: [], + }, + replaceVariables: (value: string) => value, + theme: getTheme(), + }); + + return dataFrames[0]; +} + +function createNumberField(name: string, unit?: string): Field { + const tableFieldOptions: TableFieldOptions = { + width: TOP_TABLE_COLUMN_WIDTH, + align: 'auto', + inspect: false, + cellOptions: { type: TableCellDisplayMode.Auto }, + }; + + return { + type: FieldType.number, + name, + values: [], + config: { + unit, + custom: tableFieldOptions, + }, + }; +} + +const actionColumnWidth = 61; + +function createActionField( + onSandwich: (str?: string) => void, + onSearch: (str: string) => void, + search?: string, + sandwichItem?: string +): Field { + const options: TableCustomCellOptions = { + type: TableCellDisplayMode.Custom, + cellComponent: (props) => { + return ( + + ); + }, + }; + + const actionFieldTableConfig: TableFieldOptions = { + filterable: false, + width: actionColumnWidth, + hideHeader: true, + inspect: false, + align: 'auto', + cellOptions: options, + }; + + return { + type: FieldType.number, + name: 'actions', + values: [], + config: { + custom: actionFieldTableConfig, + }, + }; +} + +type ActionCellProps = { + frame: DataFrame; + rowIndex: number; + search?: string; + sandwichItem?: string; + onSearch: (symbol: string) => void; + onSandwich: (symbol: string) => void; +}; + +function ActionCell(props: ActionCellProps) { + const styles = getStylesActionCell(); + const symbol = props.frame.fields.find((f: Field) => f.name === 'Symbol')?.values[props.rowIndex]; + const isSearched = props.search === symbol; + const isSandwiched = props.sandwichItem === symbol; + + return ( +
+ { + props.onSearch(isSearched ? '' : symbol); + }} + /> + { + props.onSandwich(isSandwiched ? undefined : symbol); + }} + /> +
+ ); +} + +const getStyles = (height: number) => { + return { + topTableContainer: css` + label: topTableContainer; + flex-grow: 1; + flex-basis: 50%; + overflow: hidden; + ${height + ? css` + min-height: ${height}px; + ` + : ''} + `, + }; +}; + +const getStylesActionCell = () => { + return { + actionCellWrapper: css` + label: actionCellWrapper; + display: flex; + height: 24px; + `, + + actionCellButton: css` + label: actionCellButton; + margin-right: 0; + width: 24px; + `, + }; +}; + +export default FlameGraphTopTableContainer; diff --git a/packages/grafana-flamegraph/src/constants.ts b/packages/grafana-flamegraph/src/constants.ts new file mode 100644 index 00000000000..db3da0a18c0 --- /dev/null +++ b/packages/grafana-flamegraph/src/constants.ts @@ -0,0 +1,8 @@ +export const PIXELS_PER_LEVEL = 22 * window.devicePixelRatio; +export const COLLAPSE_THRESHOLD = 10 * window.devicePixelRatio; +export const HIDE_THRESHOLD = 0.5 * window.devicePixelRatio; +export const LABEL_THRESHOLD = 20 * window.devicePixelRatio; +export const BAR_BORDER_WIDTH = 0.5 * window.devicePixelRatio; +export const BAR_TEXT_PADDING_LEFT = 4 * window.devicePixelRatio; +export const MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH = 800; +export const TOP_TABLE_COLUMN_WIDTH = 120; diff --git a/packages/grafana-flamegraph/src/index.ts b/packages/grafana-flamegraph/src/index.ts new file mode 100644 index 00000000000..f04c8f1e69f --- /dev/null +++ b/packages/grafana-flamegraph/src/index.ts @@ -0,0 +1 @@ +export { default as FlameGraph, type Props } from './FlameGraphContainer'; diff --git a/packages/grafana-flamegraph/src/types.ts b/packages/grafana-flamegraph/src/types.ts new file mode 100644 index 00000000000..789252e4834 --- /dev/null +++ b/packages/grafana-flamegraph/src/types.ts @@ -0,0 +1,57 @@ +import { LevelItem } from './FlameGraph/dataTransform'; + +export type ClickedItemData = { + posX: number; + posY: number; + label: string; + item: LevelItem; + level: number; +}; + +export enum SampleUnit { + Bytes = 'bytes', + Short = 'short', + Nanoseconds = 'ns', +} + +export enum ColumnTypes { + Symbol = 'Symbol', + Self = 'Self', + Total = 'Total', +} + +export enum SelectedView { + TopTable = 'topTable', + FlameGraph = 'flameGraph', + Both = 'both', +} + +export interface TableData { + self: number; + total: number; + // For diff view + totalRight: number; +} + +export interface TopTableData { + symbol: string; + self: TopTableValue; + total: TopTableValue; +} + +export type TopTableValue = { + value: number; + unitValue: string; +}; + +export enum ColorScheme { + ValueBased = 'valueBased', + PackageBased = 'packageBased', +} + +export enum ColorSchemeDiff { + Default = 'default', + DiffColorBlind = 'diffColorBlind', +} + +export type TextAlign = 'left' | 'right'; diff --git a/packages/grafana-flamegraph/src/types/emotion-core-stub.d.ts b/packages/grafana-flamegraph/src/types/emotion-core-stub.d.ts new file mode 100644 index 00000000000..837fc035a76 --- /dev/null +++ b/packages/grafana-flamegraph/src/types/emotion-core-stub.d.ts @@ -0,0 +1,4 @@ +// This stub is required due to Storybook 6.x reliance on @emotion/core +// which causes conflicts with emotion 11 types resulting in bundled +// components throwing ts error `Property 'css' is missing in type...` +export {}; diff --git a/packages/grafana-flamegraph/tsconfig.build.json b/packages/grafana-flamegraph/tsconfig.build.json new file mode 100644 index 00000000000..df3b220ccc4 --- /dev/null +++ b/packages/grafana-flamegraph/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "paths": { + "@emotion/core": ["./src/types/emotion-core-stub.d.ts"] + } + }, + "exclude": ["**/*.test.ts*"], + "extends": "./tsconfig.json" +} diff --git a/packages/grafana-flamegraph/tsconfig.json b/packages/grafana-flamegraph/tsconfig.json new file mode 100644 index 00000000000..03aa83f469f --- /dev/null +++ b/packages/grafana-flamegraph/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "declarationDir": "./compiled", + "emitDeclarationOnly": true, + "isolatedModules": true, + "rootDirs": ["."] + }, + "exclude": ["dist/**/*"], + "extends": "@grafana/tsconfig", + "include": ["src/**/*.ts*", "../../public/app/types/*.d.ts", "../grafana-ui/src/types/*.d.ts"] +} diff --git a/packages/grafana-ui/src/components/Icon/cached.json b/packages/grafana-ui/src/components/Icon/cached.json index c86d3a2532c..4bfb615427e 100644 --- a/packages/grafana-ui/src/components/Icon/cached.json +++ b/packages/grafana-ui/src/components/Icon/cached.json @@ -1,6 +1,8 @@ [ "unicons/at", "unicons/adjust-circle", + "unicons/align-left", + "unicons/align-right", "unicons/angle-double-down", "unicons/angle-double-right", "unicons/angle-down", @@ -75,6 +77,7 @@ "unicons/forward", "unicons/graph-bar", "unicons/history", + "unicons/history-alt", "unicons/home-alt", "unicons/import", "unicons/info", @@ -150,6 +153,7 @@ "custom/gf-landscape", "custom/gf-layout-simple", "custom/gf-portrait", + "custom/gf-show-context", "custom/gf-bar-alignment-after", "custom/gf-bar-alignment-before", "custom/gf-bar-alignment-center", diff --git a/packages/grafana-ui/src/components/Icon/iconBundle.ts b/packages/grafana-ui/src/components/Icon/iconBundle.ts index 553e0d11977..18c6499f9c9 100644 --- a/packages/grafana-ui/src/components/Icon/iconBundle.ts +++ b/packages/grafana-ui/src/components/Icon/iconBundle.ts @@ -9,172 +9,176 @@ import { cacheStore } from 'react-inlinesvg'; // the list of icons live here: @grafana/ui/components/Icon/cached.json import u1000 from '../../../../../public/img/icons/unicons/at.svg'; import u1001 from '../../../../../public/img/icons/unicons/adjust-circle.svg'; -import u1002 from '../../../../../public/img/icons/unicons/angle-double-down.svg'; -import u1003 from '../../../../../public/img/icons/unicons/angle-double-right.svg'; -import u1004 from '../../../../../public/img/icons/unicons/angle-down.svg'; -import u1005 from '../../../../../public/img/icons/unicons/angle-left.svg'; -import u1006 from '../../../../../public/img/icons/unicons/angle-right.svg'; -import u1007 from '../../../../../public/img/icons/unicons/angle-up.svg'; -import u1008 from '../../../../../public/img/icons/unicons/apps.svg'; -import u1009 from '../../../../../public/img/icons/unicons/arrow.svg'; -import u1010 from '../../../../../public/img/icons/unicons/arrow-down.svg'; -import u1011 from '../../../../../public/img/icons/unicons/arrow-from-right.svg'; -import u1012 from '../../../../../public/img/icons/unicons/arrow-left.svg'; -import u1013 from '../../../../../public/img/icons/unicons/arrow-random.svg'; -import u1014 from '../../../../../public/img/icons/unicons/arrow-right.svg'; -import u1015 from '../../../../../public/img/icons/unicons/arrow-to-right.svg'; -import u1016 from '../../../../../public/img/icons/unicons/arrow-up.svg'; -import u1017 from '../../../../../public/img/icons/unicons/arrows-h.svg'; -import u1018 from '../../../../../public/img/icons/unicons/backward.svg'; -import u1019 from '../../../../../public/img/icons/unicons/bars.svg'; -import u1020 from '../../../../../public/img/icons/unicons/bell.svg'; -import u1021 from '../../../../../public/img/icons/unicons/bell-slash.svg'; -import u1022 from '../../../../../public/img/icons/unicons/bolt.svg'; -import u1023 from '../../../../../public/img/icons/unicons/book.svg'; -import u1024 from '../../../../../public/img/icons/unicons/book-open.svg'; -import u1025 from '../../../../../public/img/icons/unicons/brackets-curly.svg'; -import u1026 from '../../../../../public/img/icons/unicons/bug.svg'; -import u1027 from '../../../../../public/img/icons/unicons/building.svg'; -import u1028 from '../../../../../public/img/icons/unicons/calculator-alt.svg'; -import u1029 from '../../../../../public/img/icons/unicons/calendar-alt.svg'; -import u1030 from '../../../../../public/img/icons/unicons/calendar-slash.svg'; -import u1031 from '../../../../../public/img/icons/unicons/camera.svg'; -import u1032 from '../../../../../public/img/icons/unicons/channel-add.svg'; -import u1033 from '../../../../../public/img/icons/unicons/chart-line.svg'; -import u1034 from '../../../../../public/img/icons/unicons/check.svg'; -import u1035 from '../../../../../public/img/icons/unicons/check-circle.svg'; -import u1036 from '../../../../../public/img/icons/unicons/circle.svg'; -import u1037 from '../../../../../public/img/icons/unicons/clipboard-alt.svg'; -import u1038 from '../../../../../public/img/icons/unicons/clock-nine.svg'; -import u1039 from '../../../../../public/img/icons/unicons/cloud.svg'; -import u1040 from '../../../../../public/img/icons/unicons/cloud-download.svg'; -import u1041 from '../../../../../public/img/icons/unicons/code-branch.svg'; -import u1042 from '../../../../../public/img/icons/unicons/cog.svg'; -import u1043 from '../../../../../public/img/icons/unicons/columns.svg'; -import u1044 from '../../../../../public/img/icons/unicons/comment-alt.svg'; -import u1045 from '../../../../../public/img/icons/unicons/comment-alt-share.svg'; -import u1046 from '../../../../../public/img/icons/unicons/comments-alt.svg'; -import u1047 from '../../../../../public/img/icons/unicons/compass.svg'; -import u1048 from '../../../../../public/img/icons/unicons/copy.svg'; -import u1049 from '../../../../../public/img/icons/unicons/corner-down-right-alt.svg'; -import u1050 from '../../../../../public/img/icons/unicons/cube.svg'; -import u1051 from '../../../../../public/img/icons/unicons/dashboard.svg'; -import u1052 from '../../../../../public/img/icons/unicons/database.svg'; -import u1053 from '../../../../../public/img/icons/unicons/document-info.svg'; -import u1054 from '../../../../../public/img/icons/unicons/download-alt.svg'; -import u1055 from '../../../../../public/img/icons/unicons/draggabledots.svg'; -import u1056 from '../../../../../public/img/icons/unicons/edit.svg'; -import u1057 from '../../../../../public/img/icons/unicons/ellipsis-v.svg'; -import u1058 from '../../../../../public/img/icons/unicons/ellipsis-h.svg'; -import u1059 from '../../../../../public/img/icons/unicons/envelope.svg'; -import u1060 from '../../../../../public/img/icons/unicons/exchange-alt.svg'; -import u1061 from '../../../../../public/img/icons/unicons/exclamation-circle.svg'; -import u1062 from '../../../../../public/img/icons/unicons/exclamation-triangle.svg'; -import u1063 from '../../../../../public/img/icons/unicons/external-link-alt.svg'; -import u1064 from '../../../../../public/img/icons/unicons/eye.svg'; -import u1065 from '../../../../../public/img/icons/unicons/eye-slash.svg'; -import u1066 from '../../../../../public/img/icons/unicons/file-alt.svg'; -import u1067 from '../../../../../public/img/icons/unicons/file-blank.svg'; -import u1068 from '../../../../../public/img/icons/unicons/filter.svg'; -import u1069 from '../../../../../public/img/icons/unicons/folder.svg'; -import u1070 from '../../../../../public/img/icons/unicons/folder-open.svg'; -import u1071 from '../../../../../public/img/icons/unicons/folder-plus.svg'; -import u1072 from '../../../../../public/img/icons/unicons/folder-upload.svg'; -import u1073 from '../../../../../public/img/icons/unicons/forward.svg'; -import u1074 from '../../../../../public/img/icons/unicons/graph-bar.svg'; -import u1075 from '../../../../../public/img/icons/unicons/history.svg'; -import u1076 from '../../../../../public/img/icons/unicons/home-alt.svg'; -import u1077 from '../../../../../public/img/icons/unicons/import.svg'; -import u1078 from '../../../../../public/img/icons/unicons/info.svg'; -import u1079 from '../../../../../public/img/icons/unicons/info-circle.svg'; -import u1080 from '../../../../../public/img/icons/unicons/k6.svg'; -import u1081 from '../../../../../public/img/icons/unicons/key-skeleton-alt.svg'; -import u1082 from '../../../../../public/img/icons/unicons/keyboard.svg'; -import u1083 from '../../../../../public/img/icons/unicons/link.svg'; -import u1084 from '../../../../../public/img/icons/unicons/list-ul.svg'; -import u1085 from '../../../../../public/img/icons/unicons/lock.svg'; -import u1086 from '../../../../../public/img/icons/unicons/minus.svg'; -import u1087 from '../../../../../public/img/icons/unicons/minus-circle.svg'; -import u1088 from '../../../../../public/img/icons/unicons/mobile-android.svg'; -import u1089 from '../../../../../public/img/icons/unicons/monitor.svg'; -import u1090 from '../../../../../public/img/icons/unicons/pause.svg'; -import u1091 from '../../../../../public/img/icons/unicons/pen.svg'; -import u1092 from '../../../../../public/img/icons/unicons/play.svg'; -import u1093 from '../../../../../public/img/icons/unicons/plug.svg'; -import u1094 from '../../../../../public/img/icons/unicons/plus.svg'; -import u1095 from '../../../../../public/img/icons/unicons/plus-circle.svg'; -import u1096 from '../../../../../public/img/icons/unicons/power.svg'; -import u1097 from '../../../../../public/img/icons/unicons/presentation-play.svg'; -import u1098 from '../../../../../public/img/icons/unicons/process.svg'; -import u1099 from '../../../../../public/img/icons/unicons/question-circle.svg'; -import u1100 from '../../../../../public/img/icons/unicons/repeat.svg'; -import u1101 from '../../../../../public/img/icons/unicons/rocket.svg'; -import u1102 from '../../../../../public/img/icons/unicons/rss.svg'; -import u1103 from '../../../../../public/img/icons/unicons/save.svg'; -import u1104 from '../../../../../public/img/icons/unicons/search.svg'; -import u1105 from '../../../../../public/img/icons/unicons/search-minus.svg'; -import u1106 from '../../../../../public/img/icons/unicons/search-plus.svg'; -import u1107 from '../../../../../public/img/icons/unicons/share-alt.svg'; -import u1108 from '../../../../../public/img/icons/unicons/shield.svg'; -import u1109 from '../../../../../public/img/icons/unicons/signal.svg'; -import u1110 from '../../../../../public/img/icons/unicons/signin.svg'; -import u1111 from '../../../../../public/img/icons/unicons/signout.svg'; -import u1112 from '../../../../../public/img/icons/unicons/sitemap.svg'; -import u1113 from '../../../../../public/img/icons/unicons/slack.svg'; -import u1114 from '../../../../../public/img/icons/unicons/sliders-v-alt.svg'; -import u1115 from '../../../../../public/img/icons/unicons/sort-amount-down.svg'; -import u1116 from '../../../../../public/img/icons/unicons/sort-amount-up.svg'; -import u1117 from '../../../../../public/img/icons/unicons/square-shape.svg'; -import u1118 from '../../../../../public/img/icons/unicons/star.svg'; -import u1119 from '../../../../../public/img/icons/unicons/step-backward.svg'; -import u1120 from '../../../../../public/img/icons/unicons/sync.svg'; -import u1121 from '../../../../../public/img/icons/unicons/stopwatch.svg'; -import u1122 from '../../../../../public/img/icons/unicons/table.svg'; -import u1123 from '../../../../../public/img/icons/unicons/tag-alt.svg'; -import u1124 from '../../../../../public/img/icons/unicons/times.svg'; -import u1125 from '../../../../../public/img/icons/unicons/trash-alt.svg'; -import u1126 from '../../../../../public/img/icons/unicons/unlock.svg'; -import u1127 from '../../../../../public/img/icons/unicons/upload.svg'; -import u1128 from '../../../../../public/img/icons/unicons/user.svg'; -import u1129 from '../../../../../public/img/icons/unicons/users-alt.svg'; -import u1130 from '../../../../../public/img/icons/unicons/wrap-text.svg'; -import u1131 from '../../../../../public/img/icons/unicons/cloud-upload.svg'; -import u1132 from '../../../../../public/img/icons/unicons/credit-card.svg'; -import u1133 from '../../../../../public/img/icons/unicons/file-copy-alt.svg'; -import u1134 from '../../../../../public/img/icons/unicons/fire.svg'; -import u1135 from '../../../../../public/img/icons/unicons/hourglass.svg'; -import u1136 from '../../../../../public/img/icons/unicons/layer-group.svg'; -import u1137 from '../../../../../public/img/icons/unicons/layers-alt.svg'; -import u1138 from '../../../../../public/img/icons/unicons/line-alt.svg'; -import u1139 from '../../../../../public/img/icons/unicons/list-ui-alt.svg'; -import u1140 from '../../../../../public/img/icons/unicons/message.svg'; -import u1141 from '../../../../../public/img/icons/unicons/palette.svg'; -import u1142 from '../../../../../public/img/icons/unicons/percentage.svg'; -import u1143 from '../../../../../public/img/icons/unicons/shield-exclamation.svg'; -import u1144 from '../../../../../public/img/icons/unicons/plus-square.svg'; -import u1145 from '../../../../../public/img/icons/unicons/x.svg'; -import u1146 from '../../../../../public/img/icons/unicons/capture.svg'; -import u1147 from '../../../../../public/img/icons/custom/gf-grid.svg'; -import u1148 from '../../../../../public/img/icons/custom/gf-landscape.svg'; -import u1149 from '../../../../../public/img/icons/custom/gf-layout-simple.svg'; -import u1150 from '../../../../../public/img/icons/custom/gf-portrait.svg'; -import u1151 from '../../../../../public/img/icons/custom/gf-bar-alignment-after.svg'; -import u1152 from '../../../../../public/img/icons/custom/gf-bar-alignment-before.svg'; -import u1153 from '../../../../../public/img/icons/custom/gf-bar-alignment-center.svg'; -import u1154 from '../../../../../public/img/icons/custom/gf-interpolation-linear.svg'; -import u1155 from '../../../../../public/img/icons/custom/gf-interpolation-smooth.svg'; -import u1156 from '../../../../../public/img/icons/custom/gf-interpolation-step-after.svg'; -import u1157 from '../../../../../public/img/icons/custom/gf-interpolation-step-before.svg'; -import u1158 from '../../../../../public/img/icons/custom/gf-logs.svg'; -import u1159 from '../../../../../public/img/icons/custom/gf-movepane-left.svg'; -import u1160 from '../../../../../public/img/icons/custom/gf-movepane-right.svg'; -import u1161 from '../../../../../public/img/icons/mono/favorite.svg'; -import u1162 from '../../../../../public/img/icons/mono/grafana.svg'; -import u1163 from '../../../../../public/img/icons/mono/heart.svg'; -import u1164 from '../../../../../public/img/icons/mono/heart-break.svg'; -import u1165 from '../../../../../public/img/icons/mono/panel-add.svg'; -import u1166 from '../../../../../public/img/icons/mono/library-panel.svg'; -import u1167 from '../../../../../public/img/icons/unicons/record-audio.svg'; +import u1002 from '../../../../../public/img/icons/unicons/align-left.svg'; +import u1003 from '../../../../../public/img/icons/unicons/align-right.svg'; +import u1004 from '../../../../../public/img/icons/unicons/angle-double-down.svg'; +import u1005 from '../../../../../public/img/icons/unicons/angle-double-right.svg'; +import u1006 from '../../../../../public/img/icons/unicons/angle-down.svg'; +import u1007 from '../../../../../public/img/icons/unicons/angle-left.svg'; +import u1008 from '../../../../../public/img/icons/unicons/angle-right.svg'; +import u1009 from '../../../../../public/img/icons/unicons/angle-up.svg'; +import u1010 from '../../../../../public/img/icons/unicons/apps.svg'; +import u1011 from '../../../../../public/img/icons/unicons/arrow.svg'; +import u1012 from '../../../../../public/img/icons/unicons/arrow-down.svg'; +import u1013 from '../../../../../public/img/icons/unicons/arrow-from-right.svg'; +import u1014 from '../../../../../public/img/icons/unicons/arrow-left.svg'; +import u1015 from '../../../../../public/img/icons/unicons/arrow-random.svg'; +import u1016 from '../../../../../public/img/icons/unicons/arrow-right.svg'; +import u1017 from '../../../../../public/img/icons/unicons/arrow-to-right.svg'; +import u1018 from '../../../../../public/img/icons/unicons/arrow-up.svg'; +import u1019 from '../../../../../public/img/icons/unicons/arrows-h.svg'; +import u1020 from '../../../../../public/img/icons/unicons/backward.svg'; +import u1021 from '../../../../../public/img/icons/unicons/bars.svg'; +import u1022 from '../../../../../public/img/icons/unicons/bell.svg'; +import u1023 from '../../../../../public/img/icons/unicons/bell-slash.svg'; +import u1024 from '../../../../../public/img/icons/unicons/bolt.svg'; +import u1025 from '../../../../../public/img/icons/unicons/book.svg'; +import u1026 from '../../../../../public/img/icons/unicons/book-open.svg'; +import u1027 from '../../../../../public/img/icons/unicons/brackets-curly.svg'; +import u1028 from '../../../../../public/img/icons/unicons/bug.svg'; +import u1029 from '../../../../../public/img/icons/unicons/building.svg'; +import u1030 from '../../../../../public/img/icons/unicons/calculator-alt.svg'; +import u1031 from '../../../../../public/img/icons/unicons/calendar-alt.svg'; +import u1032 from '../../../../../public/img/icons/unicons/calendar-slash.svg'; +import u1033 from '../../../../../public/img/icons/unicons/camera.svg'; +import u1034 from '../../../../../public/img/icons/unicons/channel-add.svg'; +import u1035 from '../../../../../public/img/icons/unicons/chart-line.svg'; +import u1036 from '../../../../../public/img/icons/unicons/check.svg'; +import u1037 from '../../../../../public/img/icons/unicons/check-circle.svg'; +import u1038 from '../../../../../public/img/icons/unicons/circle.svg'; +import u1039 from '../../../../../public/img/icons/unicons/clipboard-alt.svg'; +import u1040 from '../../../../../public/img/icons/unicons/clock-nine.svg'; +import u1041 from '../../../../../public/img/icons/unicons/cloud.svg'; +import u1042 from '../../../../../public/img/icons/unicons/cloud-download.svg'; +import u1043 from '../../../../../public/img/icons/unicons/code-branch.svg'; +import u1044 from '../../../../../public/img/icons/unicons/cog.svg'; +import u1045 from '../../../../../public/img/icons/unicons/columns.svg'; +import u1046 from '../../../../../public/img/icons/unicons/comment-alt.svg'; +import u1047 from '../../../../../public/img/icons/unicons/comment-alt-share.svg'; +import u1048 from '../../../../../public/img/icons/unicons/comments-alt.svg'; +import u1049 from '../../../../../public/img/icons/unicons/compass.svg'; +import u1050 from '../../../../../public/img/icons/unicons/copy.svg'; +import u1051 from '../../../../../public/img/icons/unicons/corner-down-right-alt.svg'; +import u1052 from '../../../../../public/img/icons/unicons/cube.svg'; +import u1053 from '../../../../../public/img/icons/unicons/dashboard.svg'; +import u1054 from '../../../../../public/img/icons/unicons/database.svg'; +import u1055 from '../../../../../public/img/icons/unicons/document-info.svg'; +import u1056 from '../../../../../public/img/icons/unicons/download-alt.svg'; +import u1057 from '../../../../../public/img/icons/unicons/draggabledots.svg'; +import u1058 from '../../../../../public/img/icons/unicons/edit.svg'; +import u1059 from '../../../../../public/img/icons/unicons/ellipsis-v.svg'; +import u1060 from '../../../../../public/img/icons/unicons/ellipsis-h.svg'; +import u1061 from '../../../../../public/img/icons/unicons/envelope.svg'; +import u1062 from '../../../../../public/img/icons/unicons/exchange-alt.svg'; +import u1063 from '../../../../../public/img/icons/unicons/exclamation-circle.svg'; +import u1064 from '../../../../../public/img/icons/unicons/exclamation-triangle.svg'; +import u1065 from '../../../../../public/img/icons/unicons/external-link-alt.svg'; +import u1066 from '../../../../../public/img/icons/unicons/eye.svg'; +import u1067 from '../../../../../public/img/icons/unicons/eye-slash.svg'; +import u1068 from '../../../../../public/img/icons/unicons/file-alt.svg'; +import u1069 from '../../../../../public/img/icons/unicons/file-blank.svg'; +import u1070 from '../../../../../public/img/icons/unicons/filter.svg'; +import u1071 from '../../../../../public/img/icons/unicons/folder.svg'; +import u1072 from '../../../../../public/img/icons/unicons/folder-open.svg'; +import u1073 from '../../../../../public/img/icons/unicons/folder-plus.svg'; +import u1074 from '../../../../../public/img/icons/unicons/folder-upload.svg'; +import u1075 from '../../../../../public/img/icons/unicons/forward.svg'; +import u1076 from '../../../../../public/img/icons/unicons/graph-bar.svg'; +import u1077 from '../../../../../public/img/icons/unicons/history.svg'; +import u1078 from '../../../../../public/img/icons/unicons/history-alt.svg'; +import u1079 from '../../../../../public/img/icons/unicons/home-alt.svg'; +import u1080 from '../../../../../public/img/icons/unicons/import.svg'; +import u1081 from '../../../../../public/img/icons/unicons/info.svg'; +import u1082 from '../../../../../public/img/icons/unicons/info-circle.svg'; +import u1083 from '../../../../../public/img/icons/unicons/k6.svg'; +import u1084 from '../../../../../public/img/icons/unicons/key-skeleton-alt.svg'; +import u1085 from '../../../../../public/img/icons/unicons/keyboard.svg'; +import u1086 from '../../../../../public/img/icons/unicons/link.svg'; +import u1087 from '../../../../../public/img/icons/unicons/list-ul.svg'; +import u1088 from '../../../../../public/img/icons/unicons/lock.svg'; +import u1089 from '../../../../../public/img/icons/unicons/minus.svg'; +import u1090 from '../../../../../public/img/icons/unicons/minus-circle.svg'; +import u1091 from '../../../../../public/img/icons/unicons/mobile-android.svg'; +import u1092 from '../../../../../public/img/icons/unicons/monitor.svg'; +import u1093 from '../../../../../public/img/icons/unicons/pause.svg'; +import u1094 from '../../../../../public/img/icons/unicons/pen.svg'; +import u1095 from '../../../../../public/img/icons/unicons/play.svg'; +import u1096 from '../../../../../public/img/icons/unicons/plug.svg'; +import u1097 from '../../../../../public/img/icons/unicons/plus.svg'; +import u1098 from '../../../../../public/img/icons/unicons/plus-circle.svg'; +import u1099 from '../../../../../public/img/icons/unicons/power.svg'; +import u1100 from '../../../../../public/img/icons/unicons/presentation-play.svg'; +import u1101 from '../../../../../public/img/icons/unicons/process.svg'; +import u1102 from '../../../../../public/img/icons/unicons/question-circle.svg'; +import u1103 from '../../../../../public/img/icons/unicons/repeat.svg'; +import u1104 from '../../../../../public/img/icons/unicons/rocket.svg'; +import u1105 from '../../../../../public/img/icons/unicons/rss.svg'; +import u1106 from '../../../../../public/img/icons/unicons/save.svg'; +import u1107 from '../../../../../public/img/icons/unicons/search.svg'; +import u1108 from '../../../../../public/img/icons/unicons/search-minus.svg'; +import u1109 from '../../../../../public/img/icons/unicons/search-plus.svg'; +import u1110 from '../../../../../public/img/icons/unicons/share-alt.svg'; +import u1111 from '../../../../../public/img/icons/unicons/shield.svg'; +import u1112 from '../../../../../public/img/icons/unicons/signal.svg'; +import u1113 from '../../../../../public/img/icons/unicons/signin.svg'; +import u1114 from '../../../../../public/img/icons/unicons/signout.svg'; +import u1115 from '../../../../../public/img/icons/unicons/sitemap.svg'; +import u1116 from '../../../../../public/img/icons/unicons/slack.svg'; +import u1117 from '../../../../../public/img/icons/unicons/sliders-v-alt.svg'; +import u1118 from '../../../../../public/img/icons/unicons/sort-amount-down.svg'; +import u1119 from '../../../../../public/img/icons/unicons/sort-amount-up.svg'; +import u1120 from '../../../../../public/img/icons/unicons/square-shape.svg'; +import u1121 from '../../../../../public/img/icons/unicons/star.svg'; +import u1122 from '../../../../../public/img/icons/unicons/step-backward.svg'; +import u1123 from '../../../../../public/img/icons/unicons/sync.svg'; +import u1124 from '../../../../../public/img/icons/unicons/stopwatch.svg'; +import u1125 from '../../../../../public/img/icons/unicons/table.svg'; +import u1126 from '../../../../../public/img/icons/unicons/tag-alt.svg'; +import u1127 from '../../../../../public/img/icons/unicons/times.svg'; +import u1128 from '../../../../../public/img/icons/unicons/trash-alt.svg'; +import u1129 from '../../../../../public/img/icons/unicons/unlock.svg'; +import u1130 from '../../../../../public/img/icons/unicons/upload.svg'; +import u1131 from '../../../../../public/img/icons/unicons/user.svg'; +import u1132 from '../../../../../public/img/icons/unicons/users-alt.svg'; +import u1133 from '../../../../../public/img/icons/unicons/wrap-text.svg'; +import u1134 from '../../../../../public/img/icons/unicons/cloud-upload.svg'; +import u1135 from '../../../../../public/img/icons/unicons/credit-card.svg'; +import u1136 from '../../../../../public/img/icons/unicons/file-copy-alt.svg'; +import u1137 from '../../../../../public/img/icons/unicons/fire.svg'; +import u1138 from '../../../../../public/img/icons/unicons/hourglass.svg'; +import u1139 from '../../../../../public/img/icons/unicons/layer-group.svg'; +import u1140 from '../../../../../public/img/icons/unicons/layers-alt.svg'; +import u1141 from '../../../../../public/img/icons/unicons/line-alt.svg'; +import u1142 from '../../../../../public/img/icons/unicons/list-ui-alt.svg'; +import u1143 from '../../../../../public/img/icons/unicons/message.svg'; +import u1144 from '../../../../../public/img/icons/unicons/palette.svg'; +import u1145 from '../../../../../public/img/icons/unicons/percentage.svg'; +import u1146 from '../../../../../public/img/icons/unicons/shield-exclamation.svg'; +import u1147 from '../../../../../public/img/icons/unicons/plus-square.svg'; +import u1148 from '../../../../../public/img/icons/unicons/x.svg'; +import u1149 from '../../../../../public/img/icons/unicons/capture.svg'; +import u1150 from '../../../../../public/img/icons/custom/gf-grid.svg'; +import u1151 from '../../../../../public/img/icons/custom/gf-landscape.svg'; +import u1152 from '../../../../../public/img/icons/custom/gf-layout-simple.svg'; +import u1153 from '../../../../../public/img/icons/custom/gf-portrait.svg'; +import u1154 from '../../../../../public/img/icons/custom/gf-show-context.svg'; +import u1155 from '../../../../../public/img/icons/custom/gf-bar-alignment-after.svg'; +import u1156 from '../../../../../public/img/icons/custom/gf-bar-alignment-before.svg'; +import u1157 from '../../../../../public/img/icons/custom/gf-bar-alignment-center.svg'; +import u1158 from '../../../../../public/img/icons/custom/gf-interpolation-linear.svg'; +import u1159 from '../../../../../public/img/icons/custom/gf-interpolation-smooth.svg'; +import u1160 from '../../../../../public/img/icons/custom/gf-interpolation-step-after.svg'; +import u1161 from '../../../../../public/img/icons/custom/gf-interpolation-step-before.svg'; +import u1162 from '../../../../../public/img/icons/custom/gf-logs.svg'; +import u1163 from '../../../../../public/img/icons/custom/gf-movepane-left.svg'; +import u1164 from '../../../../../public/img/icons/custom/gf-movepane-right.svg'; +import u1165 from '../../../../../public/img/icons/mono/favorite.svg'; +import u1166 from '../../../../../public/img/icons/mono/grafana.svg'; +import u1167 from '../../../../../public/img/icons/mono/heart.svg'; +import u1168 from '../../../../../public/img/icons/mono/heart-break.svg'; +import u1169 from '../../../../../public/img/icons/mono/panel-add.svg'; +import u1170 from '../../../../../public/img/icons/mono/library-panel.svg'; +import u1171 from '../../../../../public/img/icons/unicons/record-audio.svg'; // do not edit this list directly // the list of icons live here: @grafana/ui/components/Icon/cached.json @@ -199,172 +203,176 @@ export function initIconCache() { // the list of icons live here: @grafana/ui/components/Icon/cached.json cacheItem(u1000, 'unicons/at.svg'); cacheItem(u1001, 'unicons/adjust-circle.svg'); - cacheItem(u1002, 'unicons/angle-double-down.svg'); - cacheItem(u1003, 'unicons/angle-double-right.svg'); - cacheItem(u1004, 'unicons/angle-down.svg'); - cacheItem(u1005, 'unicons/angle-left.svg'); - cacheItem(u1006, 'unicons/angle-right.svg'); - cacheItem(u1007, 'unicons/angle-up.svg'); - cacheItem(u1008, 'unicons/apps.svg'); - cacheItem(u1009, 'unicons/arrow.svg'); - cacheItem(u1010, 'unicons/arrow-down.svg'); - cacheItem(u1011, 'unicons/arrow-from-right.svg'); - cacheItem(u1012, 'unicons/arrow-left.svg'); - cacheItem(u1013, 'unicons/arrow-random.svg'); - cacheItem(u1014, 'unicons/arrow-right.svg'); - cacheItem(u1015, 'unicons/arrow-to-right.svg'); - cacheItem(u1016, 'unicons/arrow-up.svg'); - cacheItem(u1017, 'unicons/arrows-h.svg'); - cacheItem(u1018, 'unicons/backward.svg'); - cacheItem(u1019, 'unicons/bars.svg'); - cacheItem(u1020, 'unicons/bell.svg'); - cacheItem(u1021, 'unicons/bell-slash.svg'); - cacheItem(u1022, 'unicons/bolt.svg'); - cacheItem(u1023, 'unicons/book.svg'); - cacheItem(u1024, 'unicons/book-open.svg'); - cacheItem(u1025, 'unicons/brackets-curly.svg'); - cacheItem(u1026, 'unicons/bug.svg'); - cacheItem(u1027, 'unicons/building.svg'); - cacheItem(u1028, 'unicons/calculator-alt.svg'); - cacheItem(u1029, 'unicons/calendar-alt.svg'); - cacheItem(u1030, 'unicons/calendar-slash.svg'); - cacheItem(u1031, 'unicons/camera.svg'); - cacheItem(u1032, 'unicons/channel-add.svg'); - cacheItem(u1033, 'unicons/chart-line.svg'); - cacheItem(u1034, 'unicons/check.svg'); - cacheItem(u1035, 'unicons/check-circle.svg'); - cacheItem(u1036, 'unicons/circle.svg'); - cacheItem(u1037, 'unicons/clipboard-alt.svg'); - cacheItem(u1038, 'unicons/clock-nine.svg'); - cacheItem(u1039, 'unicons/cloud.svg'); - cacheItem(u1040, 'unicons/cloud-download.svg'); - cacheItem(u1041, 'unicons/code-branch.svg'); - cacheItem(u1042, 'unicons/cog.svg'); - cacheItem(u1043, 'unicons/columns.svg'); - cacheItem(u1044, 'unicons/comment-alt.svg'); - cacheItem(u1045, 'unicons/comment-alt-share.svg'); - cacheItem(u1046, 'unicons/comments-alt.svg'); - cacheItem(u1047, 'unicons/compass.svg'); - cacheItem(u1048, 'unicons/copy.svg'); - cacheItem(u1049, 'unicons/corner-down-right-alt.svg'); - cacheItem(u1050, 'unicons/cube.svg'); - cacheItem(u1051, 'unicons/dashboard.svg'); - cacheItem(u1052, 'unicons/database.svg'); - cacheItem(u1053, 'unicons/document-info.svg'); - cacheItem(u1054, 'unicons/download-alt.svg'); - cacheItem(u1055, 'unicons/draggabledots.svg'); - cacheItem(u1056, 'unicons/edit.svg'); - cacheItem(u1057, 'unicons/ellipsis-v.svg'); - cacheItem(u1058, 'unicons/ellipsis-h.svg'); - cacheItem(u1059, 'unicons/envelope.svg'); - cacheItem(u1060, 'unicons/exchange-alt.svg'); - cacheItem(u1061, 'unicons/exclamation-circle.svg'); - cacheItem(u1062, 'unicons/exclamation-triangle.svg'); - cacheItem(u1063, 'unicons/external-link-alt.svg'); - cacheItem(u1064, 'unicons/eye.svg'); - cacheItem(u1065, 'unicons/eye-slash.svg'); - cacheItem(u1066, 'unicons/file-alt.svg'); - cacheItem(u1067, 'unicons/file-blank.svg'); - cacheItem(u1068, 'unicons/filter.svg'); - cacheItem(u1069, 'unicons/folder.svg'); - cacheItem(u1070, 'unicons/folder-open.svg'); - cacheItem(u1071, 'unicons/folder-plus.svg'); - cacheItem(u1072, 'unicons/folder-upload.svg'); - cacheItem(u1073, 'unicons/forward.svg'); - cacheItem(u1074, 'unicons/graph-bar.svg'); - cacheItem(u1075, 'unicons/history.svg'); - cacheItem(u1076, 'unicons/home-alt.svg'); - cacheItem(u1077, 'unicons/import.svg'); - cacheItem(u1078, 'unicons/info.svg'); - cacheItem(u1079, 'unicons/info-circle.svg'); - cacheItem(u1080, 'unicons/k6.svg'); - cacheItem(u1081, 'unicons/key-skeleton-alt.svg'); - cacheItem(u1082, 'unicons/keyboard.svg'); - cacheItem(u1083, 'unicons/link.svg'); - cacheItem(u1084, 'unicons/list-ul.svg'); - cacheItem(u1085, 'unicons/lock.svg'); - cacheItem(u1086, 'unicons/minus.svg'); - cacheItem(u1087, 'unicons/minus-circle.svg'); - cacheItem(u1088, 'unicons/mobile-android.svg'); - cacheItem(u1089, 'unicons/monitor.svg'); - cacheItem(u1090, 'unicons/pause.svg'); - cacheItem(u1091, 'unicons/pen.svg'); - cacheItem(u1092, 'unicons/play.svg'); - cacheItem(u1093, 'unicons/plug.svg'); - cacheItem(u1094, 'unicons/plus.svg'); - cacheItem(u1095, 'unicons/plus-circle.svg'); - cacheItem(u1096, 'unicons/power.svg'); - cacheItem(u1097, 'unicons/presentation-play.svg'); - cacheItem(u1098, 'unicons/process.svg'); - cacheItem(u1099, 'unicons/question-circle.svg'); - cacheItem(u1100, 'unicons/repeat.svg'); - cacheItem(u1101, 'unicons/rocket.svg'); - cacheItem(u1102, 'unicons/rss.svg'); - cacheItem(u1103, 'unicons/save.svg'); - cacheItem(u1104, 'unicons/search.svg'); - cacheItem(u1105, 'unicons/search-minus.svg'); - cacheItem(u1106, 'unicons/search-plus.svg'); - cacheItem(u1107, 'unicons/share-alt.svg'); - cacheItem(u1108, 'unicons/shield.svg'); - cacheItem(u1109, 'unicons/signal.svg'); - cacheItem(u1110, 'unicons/signin.svg'); - cacheItem(u1111, 'unicons/signout.svg'); - cacheItem(u1112, 'unicons/sitemap.svg'); - cacheItem(u1113, 'unicons/slack.svg'); - cacheItem(u1114, 'unicons/sliders-v-alt.svg'); - cacheItem(u1115, 'unicons/sort-amount-down.svg'); - cacheItem(u1116, 'unicons/sort-amount-up.svg'); - cacheItem(u1117, 'unicons/square-shape.svg'); - cacheItem(u1118, 'unicons/star.svg'); - cacheItem(u1119, 'unicons/step-backward.svg'); - cacheItem(u1120, 'unicons/sync.svg'); - cacheItem(u1121, 'unicons/stopwatch.svg'); - cacheItem(u1122, 'unicons/table.svg'); - cacheItem(u1123, 'unicons/tag-alt.svg'); - cacheItem(u1124, 'unicons/times.svg'); - cacheItem(u1125, 'unicons/trash-alt.svg'); - cacheItem(u1126, 'unicons/unlock.svg'); - cacheItem(u1127, 'unicons/upload.svg'); - cacheItem(u1128, 'unicons/user.svg'); - cacheItem(u1129, 'unicons/users-alt.svg'); - cacheItem(u1130, 'unicons/wrap-text.svg'); - cacheItem(u1131, 'unicons/cloud-upload.svg'); - cacheItem(u1132, 'unicons/credit-card.svg'); - cacheItem(u1133, 'unicons/file-copy-alt.svg'); - cacheItem(u1134, 'unicons/fire.svg'); - cacheItem(u1135, 'unicons/hourglass.svg'); - cacheItem(u1136, 'unicons/layer-group.svg'); - cacheItem(u1137, 'unicons/layers-alt.svg'); - cacheItem(u1138, 'unicons/line-alt.svg'); - cacheItem(u1139, 'unicons/list-ui-alt.svg'); - cacheItem(u1140, 'unicons/message.svg'); - cacheItem(u1141, 'unicons/palette.svg'); - cacheItem(u1142, 'unicons/percentage.svg'); - cacheItem(u1143, 'unicons/shield-exclamation.svg'); - cacheItem(u1144, 'unicons/plus-square.svg'); - cacheItem(u1145, 'unicons/x.svg'); - cacheItem(u1146, 'unicons/capture.svg'); - cacheItem(u1147, 'custom/gf-grid.svg'); - cacheItem(u1148, 'custom/gf-landscape.svg'); - cacheItem(u1149, 'custom/gf-layout-simple.svg'); - cacheItem(u1150, 'custom/gf-portrait.svg'); - cacheItem(u1151, 'custom/gf-bar-alignment-after.svg'); - cacheItem(u1152, 'custom/gf-bar-alignment-before.svg'); - cacheItem(u1153, 'custom/gf-bar-alignment-center.svg'); - cacheItem(u1154, 'custom/gf-interpolation-linear.svg'); - cacheItem(u1155, 'custom/gf-interpolation-smooth.svg'); - cacheItem(u1156, 'custom/gf-interpolation-step-after.svg'); - cacheItem(u1157, 'custom/gf-interpolation-step-before.svg'); - cacheItem(u1158, 'custom/gf-logs.svg'); - cacheItem(u1159, 'custom/gf-movepane-left.svg'); - cacheItem(u1160, 'custom/gf-movepane-right.svg'); - cacheItem(u1161, 'mono/favorite.svg'); - cacheItem(u1162, 'mono/grafana.svg'); - cacheItem(u1163, 'mono/heart.svg'); - cacheItem(u1164, 'mono/heart-break.svg'); - cacheItem(u1165, 'mono/panel-add.svg'); - cacheItem(u1166, 'mono/library-panel.svg'); - cacheItem(u1167, 'unicons/record-audio.svg'); + cacheItem(u1002, 'unicons/align-left.svg'); + cacheItem(u1003, 'unicons/align-right.svg'); + cacheItem(u1004, 'unicons/angle-double-down.svg'); + cacheItem(u1005, 'unicons/angle-double-right.svg'); + cacheItem(u1006, 'unicons/angle-down.svg'); + cacheItem(u1007, 'unicons/angle-left.svg'); + cacheItem(u1008, 'unicons/angle-right.svg'); + cacheItem(u1009, 'unicons/angle-up.svg'); + cacheItem(u1010, 'unicons/apps.svg'); + cacheItem(u1011, 'unicons/arrow.svg'); + cacheItem(u1012, 'unicons/arrow-down.svg'); + cacheItem(u1013, 'unicons/arrow-from-right.svg'); + cacheItem(u1014, 'unicons/arrow-left.svg'); + cacheItem(u1015, 'unicons/arrow-random.svg'); + cacheItem(u1016, 'unicons/arrow-right.svg'); + cacheItem(u1017, 'unicons/arrow-to-right.svg'); + cacheItem(u1018, 'unicons/arrow-up.svg'); + cacheItem(u1019, 'unicons/arrows-h.svg'); + cacheItem(u1020, 'unicons/backward.svg'); + cacheItem(u1021, 'unicons/bars.svg'); + cacheItem(u1022, 'unicons/bell.svg'); + cacheItem(u1023, 'unicons/bell-slash.svg'); + cacheItem(u1024, 'unicons/bolt.svg'); + cacheItem(u1025, 'unicons/book.svg'); + cacheItem(u1026, 'unicons/book-open.svg'); + cacheItem(u1027, 'unicons/brackets-curly.svg'); + cacheItem(u1028, 'unicons/bug.svg'); + cacheItem(u1029, 'unicons/building.svg'); + cacheItem(u1030, 'unicons/calculator-alt.svg'); + cacheItem(u1031, 'unicons/calendar-alt.svg'); + cacheItem(u1032, 'unicons/calendar-slash.svg'); + cacheItem(u1033, 'unicons/camera.svg'); + cacheItem(u1034, 'unicons/channel-add.svg'); + cacheItem(u1035, 'unicons/chart-line.svg'); + cacheItem(u1036, 'unicons/check.svg'); + cacheItem(u1037, 'unicons/check-circle.svg'); + cacheItem(u1038, 'unicons/circle.svg'); + cacheItem(u1039, 'unicons/clipboard-alt.svg'); + cacheItem(u1040, 'unicons/clock-nine.svg'); + cacheItem(u1041, 'unicons/cloud.svg'); + cacheItem(u1042, 'unicons/cloud-download.svg'); + cacheItem(u1043, 'unicons/code-branch.svg'); + cacheItem(u1044, 'unicons/cog.svg'); + cacheItem(u1045, 'unicons/columns.svg'); + cacheItem(u1046, 'unicons/comment-alt.svg'); + cacheItem(u1047, 'unicons/comment-alt-share.svg'); + cacheItem(u1048, 'unicons/comments-alt.svg'); + cacheItem(u1049, 'unicons/compass.svg'); + cacheItem(u1050, 'unicons/copy.svg'); + cacheItem(u1051, 'unicons/corner-down-right-alt.svg'); + cacheItem(u1052, 'unicons/cube.svg'); + cacheItem(u1053, 'unicons/dashboard.svg'); + cacheItem(u1054, 'unicons/database.svg'); + cacheItem(u1055, 'unicons/document-info.svg'); + cacheItem(u1056, 'unicons/download-alt.svg'); + cacheItem(u1057, 'unicons/draggabledots.svg'); + cacheItem(u1058, 'unicons/edit.svg'); + cacheItem(u1059, 'unicons/ellipsis-v.svg'); + cacheItem(u1060, 'unicons/ellipsis-h.svg'); + cacheItem(u1061, 'unicons/envelope.svg'); + cacheItem(u1062, 'unicons/exchange-alt.svg'); + cacheItem(u1063, 'unicons/exclamation-circle.svg'); + cacheItem(u1064, 'unicons/exclamation-triangle.svg'); + cacheItem(u1065, 'unicons/external-link-alt.svg'); + cacheItem(u1066, 'unicons/eye.svg'); + cacheItem(u1067, 'unicons/eye-slash.svg'); + cacheItem(u1068, 'unicons/file-alt.svg'); + cacheItem(u1069, 'unicons/file-blank.svg'); + cacheItem(u1070, 'unicons/filter.svg'); + cacheItem(u1071, 'unicons/folder.svg'); + cacheItem(u1072, 'unicons/folder-open.svg'); + cacheItem(u1073, 'unicons/folder-plus.svg'); + cacheItem(u1074, 'unicons/folder-upload.svg'); + cacheItem(u1075, 'unicons/forward.svg'); + cacheItem(u1076, 'unicons/graph-bar.svg'); + cacheItem(u1077, 'unicons/history.svg'); + cacheItem(u1078, 'unicons/history-alt.svg'); + cacheItem(u1079, 'unicons/home-alt.svg'); + cacheItem(u1080, 'unicons/import.svg'); + cacheItem(u1081, 'unicons/info.svg'); + cacheItem(u1082, 'unicons/info-circle.svg'); + cacheItem(u1083, 'unicons/k6.svg'); + cacheItem(u1084, 'unicons/key-skeleton-alt.svg'); + cacheItem(u1085, 'unicons/keyboard.svg'); + cacheItem(u1086, 'unicons/link.svg'); + cacheItem(u1087, 'unicons/list-ul.svg'); + cacheItem(u1088, 'unicons/lock.svg'); + cacheItem(u1089, 'unicons/minus.svg'); + cacheItem(u1090, 'unicons/minus-circle.svg'); + cacheItem(u1091, 'unicons/mobile-android.svg'); + cacheItem(u1092, 'unicons/monitor.svg'); + cacheItem(u1093, 'unicons/pause.svg'); + cacheItem(u1094, 'unicons/pen.svg'); + cacheItem(u1095, 'unicons/play.svg'); + cacheItem(u1096, 'unicons/plug.svg'); + cacheItem(u1097, 'unicons/plus.svg'); + cacheItem(u1098, 'unicons/plus-circle.svg'); + cacheItem(u1099, 'unicons/power.svg'); + cacheItem(u1100, 'unicons/presentation-play.svg'); + cacheItem(u1101, 'unicons/process.svg'); + cacheItem(u1102, 'unicons/question-circle.svg'); + cacheItem(u1103, 'unicons/repeat.svg'); + cacheItem(u1104, 'unicons/rocket.svg'); + cacheItem(u1105, 'unicons/rss.svg'); + cacheItem(u1106, 'unicons/save.svg'); + cacheItem(u1107, 'unicons/search.svg'); + cacheItem(u1108, 'unicons/search-minus.svg'); + cacheItem(u1109, 'unicons/search-plus.svg'); + cacheItem(u1110, 'unicons/share-alt.svg'); + cacheItem(u1111, 'unicons/shield.svg'); + cacheItem(u1112, 'unicons/signal.svg'); + cacheItem(u1113, 'unicons/signin.svg'); + cacheItem(u1114, 'unicons/signout.svg'); + cacheItem(u1115, 'unicons/sitemap.svg'); + cacheItem(u1116, 'unicons/slack.svg'); + cacheItem(u1117, 'unicons/sliders-v-alt.svg'); + cacheItem(u1118, 'unicons/sort-amount-down.svg'); + cacheItem(u1119, 'unicons/sort-amount-up.svg'); + cacheItem(u1120, 'unicons/square-shape.svg'); + cacheItem(u1121, 'unicons/star.svg'); + cacheItem(u1122, 'unicons/step-backward.svg'); + cacheItem(u1123, 'unicons/sync.svg'); + cacheItem(u1124, 'unicons/stopwatch.svg'); + cacheItem(u1125, 'unicons/table.svg'); + cacheItem(u1126, 'unicons/tag-alt.svg'); + cacheItem(u1127, 'unicons/times.svg'); + cacheItem(u1128, 'unicons/trash-alt.svg'); + cacheItem(u1129, 'unicons/unlock.svg'); + cacheItem(u1130, 'unicons/upload.svg'); + cacheItem(u1131, 'unicons/user.svg'); + cacheItem(u1132, 'unicons/users-alt.svg'); + cacheItem(u1133, 'unicons/wrap-text.svg'); + cacheItem(u1134, 'unicons/cloud-upload.svg'); + cacheItem(u1135, 'unicons/credit-card.svg'); + cacheItem(u1136, 'unicons/file-copy-alt.svg'); + cacheItem(u1137, 'unicons/fire.svg'); + cacheItem(u1138, 'unicons/hourglass.svg'); + cacheItem(u1139, 'unicons/layer-group.svg'); + cacheItem(u1140, 'unicons/layers-alt.svg'); + cacheItem(u1141, 'unicons/line-alt.svg'); + cacheItem(u1142, 'unicons/list-ui-alt.svg'); + cacheItem(u1143, 'unicons/message.svg'); + cacheItem(u1144, 'unicons/palette.svg'); + cacheItem(u1145, 'unicons/percentage.svg'); + cacheItem(u1146, 'unicons/shield-exclamation.svg'); + cacheItem(u1147, 'unicons/plus-square.svg'); + cacheItem(u1148, 'unicons/x.svg'); + cacheItem(u1149, 'unicons/capture.svg'); + cacheItem(u1150, 'custom/gf-grid.svg'); + cacheItem(u1151, 'custom/gf-landscape.svg'); + cacheItem(u1152, 'custom/gf-layout-simple.svg'); + cacheItem(u1153, 'custom/gf-portrait.svg'); + cacheItem(u1154, 'custom/gf-show-context.svg'); + cacheItem(u1155, 'custom/gf-bar-alignment-after.svg'); + cacheItem(u1156, 'custom/gf-bar-alignment-before.svg'); + cacheItem(u1157, 'custom/gf-bar-alignment-center.svg'); + cacheItem(u1158, 'custom/gf-interpolation-linear.svg'); + cacheItem(u1159, 'custom/gf-interpolation-smooth.svg'); + cacheItem(u1160, 'custom/gf-interpolation-step-after.svg'); + cacheItem(u1161, 'custom/gf-interpolation-step-before.svg'); + cacheItem(u1162, 'custom/gf-logs.svg'); + cacheItem(u1163, 'custom/gf-movepane-left.svg'); + cacheItem(u1164, 'custom/gf-movepane-right.svg'); + cacheItem(u1165, 'mono/favorite.svg'); + cacheItem(u1166, 'mono/grafana.svg'); + cacheItem(u1167, 'mono/heart.svg'); + cacheItem(u1168, 'mono/heart-break.svg'); + cacheItem(u1169, 'mono/panel-add.svg'); + cacheItem(u1170, 'mono/library-panel.svg'); + cacheItem(u1171, 'unicons/record-audio.svg'); // do not edit this list directly // the list of icons live here: @grafana/ui/components/Icon/cached.json } diff --git a/packages/grafana-ui/src/components/Table/types.ts b/packages/grafana-ui/src/components/Table/types.ts index 24747c5514e..1cb4f5d85b4 100644 --- a/packages/grafana-ui/src/components/Table/types.ts +++ b/packages/grafana-ui/src/components/Table/types.ts @@ -7,7 +7,18 @@ import * as schema from '@grafana/schema'; import { TableStyles } from './styles'; -export { type FieldTextAlignment, TableCellBackgroundDisplayMode, TableCellDisplayMode } from '@grafana/schema'; +export { + type FieldTextAlignment, + TableCellBackgroundDisplayMode, + TableCellDisplayMode, + type TableAutoCellOptions, + type TableSparklineCellOptions, + type TableBarGaugeCellOptions, + type TableColoredBackgroundCellOptions, + type TableColorTextCellOptions, + type TableImageCellOptions, + type TableJsonViewCellOptions, +} from '@grafana/schema'; export interface TableRow { [x: string]: any; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 8c82bb8fc88..107f56f278b 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -90,6 +90,13 @@ export { type TableSortByFieldState, type TableFooterCalc, type AdHocFilterItem, + type TableAutoCellOptions, + type TableSparklineCellOptions, + type TableBarGaugeCellOptions, + type TableColoredBackgroundCellOptions, + type TableColorTextCellOptions, + type TableImageCellOptions, + type TableJsonViewCellOptions, } from './Table/types'; export { TableInputCSV } from './TableInputCSV/TableInputCSV'; export { TabsBar } from './Tabs/TabsBar'; diff --git a/pkg/build/npm/npm.go b/pkg/build/npm/npm.go index 6663b749bf3..5b1a895ec49 100644 --- a/pkg/build/npm/npm.go +++ b/pkg/build/npm/npm.go @@ -25,6 +25,7 @@ var packages = []string{ "@grafana/e2e", "@grafana/e2e-selectors", "@grafana/schema", + "@grafana/flamegraph", } // PublishNpmPackages will publish local NPM packages to NPM registry. diff --git a/public/app/features/explore/FlameGraph/FlameGraphExploreContainer.tsx b/public/app/features/explore/FlameGraph/FlameGraphExploreContainer.tsx index a7ace9b8794..2327bf17124 100644 --- a/public/app/features/explore/FlameGraph/FlameGraphExploreContainer.tsx +++ b/public/app/features/explore/FlameGraph/FlameGraphExploreContainer.tsx @@ -2,19 +2,36 @@ import { css } from '@emotion/css'; import React from 'react'; import { DataFrame, GrafanaTheme2, CoreApp } from '@grafana/data'; +import { FlameGraph } from '@grafana/flamegraph'; +import { reportInteraction, config } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; -import FlameGraphContainer from 'app/plugins/panel/flamegraph/components/FlameGraphContainer'; interface Props { dataFrames: DataFrame[]; } +function interaction(name: string, context: Record = {}) { + reportInteraction(`grafana_flamegraph_${name}`, { + app: CoreApp.Unknown, + grafana_version: config.buildInfo.version, + ...context, + }); +} + export const FlameGraphExploreContainer = (props: Props) => { const styles = useStyles2((theme) => getStyles(theme)); return (
- + config.theme2} + onTableSymbolClick={() => interaction('table_item_selected')} + onViewSelected={(view: string) => interaction('view_selected', { view })} + onTextAlignSelected={(align: string) => interaction('text_align_selected', { align })} + onTableSort={(sort: string) => interaction('table_sort_selected', { sort })} + />
); }; diff --git a/public/app/plugins/panel/flamegraph/FlameGraphPanel.tsx b/public/app/plugins/panel/flamegraph/FlameGraphPanel.tsx index ba1e13a2674..5fab9a4dbb9 100644 --- a/public/app/plugins/panel/flamegraph/FlameGraphPanel.tsx +++ b/public/app/plugins/panel/flamegraph/FlameGraphPanel.tsx @@ -1,10 +1,19 @@ import React from 'react'; import { CoreApp, PanelProps } from '@grafana/data'; -import { PanelDataErrorView } from '@grafana/runtime'; +import { FlameGraph } from '@grafana/flamegraph'; +import { PanelDataErrorView, reportInteraction, config } from '@grafana/runtime'; import { checkFields, getMessageCheckFieldsResult } from './components/FlameGraph/dataTransform'; -import FlameGraphContainer from './components/FlameGraphContainer'; +// import FlameGraphContainer from './components/FlameGraphContainer'; + +function interaction(name: string, context: Record = {}) { + reportInteraction(`grafana_flamegraph_${name}`, { + app: CoreApp.Unknown, + grafana_version: config.buildInfo.version, + ...context, + }); +} export const FlameGraphPanel = (props: PanelProps) => { const wrongFields = checkFields(props.data.series[0]); @@ -13,5 +22,16 @@ export const FlameGraphPanel = (props: PanelProps) => { ); } - return ; + + return ( + config.theme2} + onTableSymbolClick={() => interaction('table_item_selected')} + onViewSelected={(view: string) => interaction('view_selected', { view })} + onTextAlignSelected={(align: string) => interaction('text_align_selected', { align })} + onTableSort={(sort: string) => interaction('table_sort_selected', { sort })} + /> + ); }; diff --git a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx index 1da0ef7244b..730bd29b533 100644 --- a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx +++ b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx @@ -244,7 +244,7 @@ type ActionCellProps = { function ActionCell(props: ActionCellProps) { const styles = useStyles2(getStyles); - const symbol = props.frame.fields.find((f: Field) => f.name === 'Symbol')?.values.get(props.rowIndex); + const symbol = props.frame.fields.find((f: Field) => f.name === 'Symbol')?.values[props.rowIndex]; const isSearched = props.search === symbol; const isSandwiched = props.sandwichItem === symbol; diff --git a/yarn.lock b/yarn.lock index 1e530ed3683..c55c474ca77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1": +"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.3.0": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f @@ -3856,6 +3856,51 @@ __metadata: languageName: node linkType: hard +"@grafana/flamegraph@workspace:*, @grafana/flamegraph@workspace:packages/grafana-flamegraph": + version: 0.0.0-use.local + resolution: "@grafana/flamegraph@workspace:packages/grafana-flamegraph" + dependencies: + "@babel/core": 7.22.9 + "@babel/preset-env": 7.22.9 + "@babel/preset-react": 7.22.5 + "@emotion/css": 11.11.2 + "@grafana/data": 10.2.0-pre + "@grafana/tsconfig": ^1.2.0-rc1 + "@grafana/ui": 10.2.0-pre + "@leeoniya/ufuzzy": 1.0.8 + "@rollup/plugin-node-resolve": 15.1.0 + "@testing-library/jest-dom": ^6.1.2 + "@testing-library/react": 14.0.0 + "@testing-library/user-event": 14.4.3 + "@types/d3": ^7 + "@types/jest": ^29.5.4 + "@types/lodash": 4.14.195 + "@types/react": 18.2.15 + "@types/react-virtualized-auto-sizer": 1.0.1 + "@types/tinycolor2": 1.4.3 + babel-jest: 29.3.1 + d3: ^7.8.5 + jest: ^29.6.4 + jest-canvas-mock: 2.5.2 + lodash: 4.17.21 + react: 18.2.0 + react-use: 17.4.0 + react-virtualized-auto-sizer: 1.0.7 + rollup: 2.79.1 + rollup-plugin-dts: ^5.0.0 + rollup-plugin-esbuild: 5.0.0 + rollup-plugin-node-externals: ^5.0.0 + tinycolor2: 1.6.0 + ts-jest: 29.1.1 + ts-node: 10.9.1 + tslib: 2.6.0 + typescript: 4.8.4 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + languageName: unknown + linkType: soft + "@grafana/google-sdk@npm:0.1.1": version: 0.1.1 resolution: "@grafana/google-sdk@npm:0.1.1" @@ -4292,6 +4337,20 @@ __metadata: languageName: node linkType: hard +"@jest/console@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/console@npm:29.6.4" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^29.6.3 + jest-util: ^29.6.3 + slash: ^3.0.0 + checksum: 1caf061a39266b86e96ca13358401839e4d930742cbaa9e87e79d7ce170a83195e52e5b2d22eb5aa9a949219b61a163a81e337ec98b8323d88d79853051df96c + languageName: node + linkType: hard + "@jest/core@npm:^29.3.1": version: 29.3.1 resolution: "@jest/core@npm:29.3.1" @@ -4333,6 +4392,47 @@ __metadata: languageName: node linkType: hard +"@jest/core@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/core@npm:29.6.4" + dependencies: + "@jest/console": ^29.6.4 + "@jest/reporters": ^29.6.4 + "@jest/test-result": ^29.6.4 + "@jest/transform": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + ci-info: ^3.2.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-changed-files: ^29.6.3 + jest-config: ^29.6.4 + jest-haste-map: ^29.6.4 + jest-message-util: ^29.6.3 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.6.4 + jest-resolve-dependencies: ^29.6.4 + jest-runner: ^29.6.4 + jest-runtime: ^29.6.4 + jest-snapshot: ^29.6.4 + jest-util: ^29.6.3 + jest-validate: ^29.6.3 + jest-watcher: ^29.6.4 + micromatch: ^4.0.4 + pretty-format: ^29.6.3 + slash: ^3.0.0 + strip-ansi: ^6.0.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 0f36532c909775814cb7d4310d61881beaefdec6229ef0b7493c6191dfca20ae5222120846ea5ef8cdeaa8cef265aae9cea8989dcab572d8daea9afd14247c7a + languageName: node + linkType: hard + "@jest/environment@npm:^29.3.1": version: 29.3.1 resolution: "@jest/environment@npm:29.3.1" @@ -4345,6 +4445,18 @@ __metadata: languageName: node linkType: hard +"@jest/environment@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/environment@npm:29.6.4" + dependencies: + "@jest/fake-timers": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.6.3 + checksum: 810d8f1fc26d293acfc44927bcb78adc58ed4ea580a64c8d94aa6c67239dcb149186bf25b94ff28b79de15253e0c877ad8d330feac205f185f3517593168510c + languageName: node + linkType: hard + "@jest/expect-utils@npm:^29.3.1": version: 29.3.1 resolution: "@jest/expect-utils@npm:29.3.1" @@ -4354,6 +4466,15 @@ __metadata: languageName: node linkType: hard +"@jest/expect-utils@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/expect-utils@npm:29.6.4" + dependencies: + jest-get-type: ^29.6.3 + checksum: a17059e02a4c0fca98e2abb7e9e58c70df3cd3d4ebcc6a960cb57c571726f7bd738c6cd008a9bf99770b77e92f7e21c75fe1f9ceec9b7a7710010f9340bb28ad + languageName: node + linkType: hard + "@jest/expect@npm:^29.3.1": version: 29.3.1 resolution: "@jest/expect@npm:29.3.1" @@ -4364,6 +4485,16 @@ __metadata: languageName: node linkType: hard +"@jest/expect@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/expect@npm:29.6.4" + dependencies: + expect: ^29.6.4 + jest-snapshot: ^29.6.4 + checksum: e9d7306a96e2f9f9f7a0d93d41850cbad987ebda951a5d9a63d3f5fb61da4c1e41adb54af7f7222e4a185454ecb17ddc77845e18001ee28ac114f7a7fe9e671d + languageName: node + linkType: hard + "@jest/fake-timers@npm:^29.3.1": version: 29.3.1 resolution: "@jest/fake-timers@npm:29.3.1" @@ -4378,6 +4509,20 @@ __metadata: languageName: node linkType: hard +"@jest/fake-timers@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/fake-timers@npm:29.6.4" + dependencies: + "@jest/types": ^29.6.3 + "@sinonjs/fake-timers": ^10.0.2 + "@types/node": "*" + jest-message-util: ^29.6.3 + jest-mock: ^29.6.3 + jest-util: ^29.6.3 + checksum: 3f06d1090cbaaf781920fe59b10509ad86b587c401818a066ee1550101c6203e0718f0f83bbd2afa8bdf7b43eb280f89fb9f8c98886094e53ccabe5e64de9be1 + languageName: node + linkType: hard + "@jest/globals@npm:^29.3.1": version: 29.3.1 resolution: "@jest/globals@npm:29.3.1" @@ -4390,6 +4535,18 @@ __metadata: languageName: node linkType: hard +"@jest/globals@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/globals@npm:29.6.4" + dependencies: + "@jest/environment": ^29.6.4 + "@jest/expect": ^29.6.4 + "@jest/types": ^29.6.3 + jest-mock: ^29.6.3 + checksum: a41b18871a248151264668a38b13cb305f03db112bfd89ec44e858af0e79066e0b03d6b68c8baf1ec6c578be6fdb87519389c83438608b91471d17a5724858e0 + languageName: node + linkType: hard + "@jest/reporters@npm:^29.3.1": version: 29.3.1 resolution: "@jest/reporters@npm:29.3.1" @@ -4427,6 +4584,43 @@ __metadata: languageName: node linkType: hard +"@jest/reporters@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/reporters@npm:29.6.4" + dependencies: + "@bcoe/v8-coverage": ^0.2.3 + "@jest/console": ^29.6.4 + "@jest/test-result": ^29.6.4 + "@jest/transform": ^29.6.4 + "@jest/types": ^29.6.3 + "@jridgewell/trace-mapping": ^0.3.18 + "@types/node": "*" + chalk: ^4.0.0 + collect-v8-coverage: ^1.0.0 + exit: ^0.1.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + istanbul-lib-coverage: ^3.0.0 + istanbul-lib-instrument: ^6.0.0 + istanbul-lib-report: ^3.0.0 + istanbul-lib-source-maps: ^4.0.0 + istanbul-reports: ^3.1.3 + jest-message-util: ^29.6.3 + jest-util: ^29.6.3 + jest-worker: ^29.6.4 + slash: ^3.0.0 + string-length: ^4.0.1 + strip-ansi: ^6.0.0 + v8-to-istanbul: ^9.0.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 9ee0db497f3a826f535d3af0575ceb67984f9708bc6386450359517c212c67218ae98b8ea93ab05df2f920aed9c4166ef64209d66a09b7e30fc0077c91347ad0 + languageName: node + linkType: hard + "@jest/schemas@npm:^29.0.0": version: 29.0.0 resolution: "@jest/schemas@npm:29.0.0" @@ -4454,6 +4648,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + "@jest/source-map@npm:^29.2.0": version: 29.2.0 resolution: "@jest/source-map@npm:29.2.0" @@ -4465,6 +4668,17 @@ __metadata: languageName: node linkType: hard +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" + dependencies: + "@jridgewell/trace-mapping": ^0.3.18 + callsites: ^3.0.0 + graceful-fs: ^4.2.9 + checksum: bcc5a8697d471396c0003b0bfa09722c3cd879ad697eb9c431e6164e2ea7008238a01a07193dfe3cbb48b1d258eb7251f6efcea36f64e1ebc464ea3c03ae2deb + languageName: node + linkType: hard + "@jest/test-result@npm:^29.3.1": version: 29.3.1 resolution: "@jest/test-result@npm:29.3.1" @@ -4477,6 +4691,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-result@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/test-result@npm:29.6.4" + dependencies: + "@jest/console": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: a13c82d29038e80059191a1a443240678c6934ea832fdabaec12b3ece397b6303022a064494a6bbd167a024f04e6b4d9ace1001300927ff70405ec9d854f1193 + languageName: node + linkType: hard + "@jest/test-sequencer@npm:^29.3.1": version: 29.3.1 resolution: "@jest/test-sequencer@npm:29.3.1" @@ -4489,6 +4715,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-sequencer@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/test-sequencer@npm:29.6.4" + dependencies: + "@jest/test-result": ^29.6.4 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.4 + slash: ^3.0.0 + checksum: 517fc66b74a87431a8a1429e4505d85bd09c11f2ba835e46c07c79911fbee23b89c01ec444c7c1d12d1b36f9eba60fcbbccc8e1bc1ae54a1a8b03b5f530ff81b + languageName: node + linkType: hard + "@jest/transform@npm:^29.3.1": version: 29.3.1 resolution: "@jest/transform@npm:29.3.1" @@ -4512,6 +4750,29 @@ __metadata: languageName: node linkType: hard +"@jest/transform@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/transform@npm:29.6.4" + dependencies: + "@babel/core": ^7.11.6 + "@jest/types": ^29.6.3 + "@jridgewell/trace-mapping": ^0.3.18 + babel-plugin-istanbul: ^6.1.1 + chalk: ^4.0.0 + convert-source-map: ^2.0.0 + fast-json-stable-stringify: ^2.1.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.4 + jest-regex-util: ^29.6.3 + jest-util: ^29.6.3 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.2 + checksum: 0341a200a0bb926fc67ab9aede91c7b4009458206495e92057e72a115c55da5fed117457e68c6ea821e24c58b55da75c6a7b0f272ed63c2693db583d689a3383 + languageName: node + linkType: hard + "@jest/types@npm:^26.6.2": version: 26.6.2 resolution: "@jest/types@npm:26.6.2" @@ -4580,6 +4841,20 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" + dependencies: + "@jest/schemas": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: a0bcf15dbb0eca6bdd8ce61a3fb055349d40268622a7670a3b2eb3c3dbafe9eb26af59938366d520b86907b9505b0f9b29b85cec11579a9e580694b87cd90fcc + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.1.0": version: 0.1.1 resolution: "@jridgewell/gen-mapping@npm:0.1.1" @@ -9174,6 +9449,36 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:^6.1.2": + version: 6.1.2 + resolution: "@testing-library/jest-dom@npm:6.1.2" + dependencies: + "@adobe/css-tools": ^4.3.0 + "@babel/runtime": ^7.9.2 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.5.6 + lodash: ^4.17.15 + redent: ^3.0.0 + peerDependencies: + "@jest/globals": ">= 28" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: de6b7f98d1b42887192eb70fd917b2b98d92aab22a86801718de75e0ca4964589335efeb650b0f7b9859609446b20d2bd81bfc5755f1655885d5664d1c093a70 + languageName: node + linkType: hard + "@testing-library/react-hooks@npm:^8.0.1": version: 8.0.1 resolution: "@testing-library/react-hooks@npm:8.0.1" @@ -9705,7 +10010,7 @@ __metadata: languageName: node linkType: hard -"@types/d3@npm:7.4.0": +"@types/d3@npm:7.4.0, @types/d3@npm:^7": version: 7.4.0 resolution: "@types/d3@npm:7.4.0" dependencies: @@ -10058,7 +10363,7 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:29.5.4": +"@types/jest@npm:29.5.4, @types/jest@npm:^29.5.4": version: 29.5.4 resolution: "@types/jest@npm:29.5.4" dependencies: @@ -12791,6 +13096,23 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:^29.6.4": + version: 29.6.4 + resolution: "babel-jest@npm:29.6.4" + dependencies: + "@jest/transform": ^29.6.4 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^29.6.3 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + slash: ^3.0.0 + peerDependencies: + "@babel/core": ^7.8.0 + checksum: c574f1805ab6b51a7d0f5a028aad19eec4634be81e66e6f4631b79b34d8ea05dfb53629f3686c77345163872730aa0408c9e5937ed85f846984228f7ab5e5d96 + languageName: node + linkType: hard + "babel-loader@npm:9.1.3, babel-loader@npm:^9.0.0": version: 9.1.3 resolution: "babel-loader@npm:9.1.3" @@ -12865,6 +13187,18 @@ __metadata: languageName: node linkType: hard +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" + dependencies: + "@babel/template": ^7.3.3 + "@babel/types": ^7.3.3 + "@types/babel__core": ^7.1.14 + "@types/babel__traverse": ^7.0.6 + checksum: 51250f22815a7318f17214a9d44650ba89551e6d4f47a2dc259128428324b52f5a73979d010cefd921fd5a720d8c1d55ad74ff601cd94c7bd44d5f6292fde2d1 + languageName: node + linkType: hard + "babel-plugin-macros@npm:3.1.0, babel-plugin-macros@npm:^3.1.0": version: 3.1.0 resolution: "babel-plugin-macros@npm:3.1.0" @@ -13018,6 +13352,18 @@ __metadata: languageName: node linkType: hard +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" + dependencies: + babel-plugin-jest-hoist: ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: aa4ff2a8a728d9d698ed521e3461a109a1e66202b13d3494e41eea30729a5e7cc03b3a2d56c594423a135429c37bf63a9fa8b0b9ce275298be3095a88c69f6fb + languageName: node + linkType: hard + "babel-runtime@npm:6.x, babel-runtime@npm:^6.26.0": version: 6.26.0 resolution: "babel-runtime@npm:6.26.0" @@ -15617,7 +15963,7 @@ __metadata: languageName: node linkType: hard -"d3@npm:7.8.5": +"d3@npm:7.8.5, d3@npm:^7.8.5": version: 7.8.5 resolution: "d3@npm:7.8.5" dependencies: @@ -15847,6 +16193,18 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.0.0": + version: 1.5.1 + resolution: "dedent@npm:1.5.1" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: c3c300a14edf1bdf5a873f9e4b22e839d62490bc5c8d6169c1f15858a1a76733d06a9a56930e963d677a2ceeca4b6b0894cc5ea2f501aa382ca5b92af3413c2a + languageName: node + linkType: hard + "deep-equal@npm:^2.0.5": version: 2.2.0 resolution: "deep-equal@npm:2.2.0" @@ -16116,6 +16474,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa + languageName: node + linkType: hard + "diff@npm:5.0.0": version: 5.0.0 resolution: "diff@npm:5.0.0" @@ -17784,6 +18149,19 @@ __metadata: languageName: node linkType: hard +"expect@npm:^29.6.4": + version: 29.6.4 + resolution: "expect@npm:29.6.4" + dependencies: + "@jest/expect-utils": ^29.6.4 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.6.4 + jest-message-util: ^29.6.3 + jest-util: ^29.6.3 + checksum: 019b187d665562e4948b239e011a8791363e916f3076a229298d625e67fdadb06e8c2748798c49b4cf418ea223673eadd1de06537e08ba3c055c6f0efefc2306 + languageName: node + linkType: hard + "expose-loader@npm:4.1.0": version: 4.1.0 resolution: "expose-loader@npm:4.1.0" @@ -19283,6 +19661,7 @@ __metadata: "@grafana/experimental": 1.7.0 "@grafana/faro-core": 1.1.2 "@grafana/faro-web-sdk": 1.1.2 + "@grafana/flamegraph": "workspace:*" "@grafana/google-sdk": 0.1.1 "@grafana/lezer-logql": 0.1.11 "@grafana/lezer-traceql": 0.0.5 @@ -21512,6 +21891,19 @@ __metadata: languageName: node linkType: hard +"istanbul-lib-instrument@npm:^6.0.0": + version: 6.0.0 + resolution: "istanbul-lib-instrument@npm:6.0.0" + dependencies: + "@babel/core": ^7.12.3 + "@babel/parser": ^7.14.7 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-coverage: ^3.2.0 + semver: ^7.5.4 + checksum: b9dc3723a769e65dbe1b912f935088ffc07cf393fa78a3ce79022c91aabb0ad01405ffd56083cdd822e514798e9daae3ea7bfe85633b094ecb335d28eb0a3f97 + languageName: node + linkType: hard + "istanbul-lib-report@npm:^3.0.0": version: 3.0.0 resolution: "istanbul-lib-report@npm:3.0.0" @@ -21601,6 +21993,17 @@ __metadata: languageName: node linkType: hard +"jest-changed-files@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-changed-files@npm:29.6.3" + dependencies: + execa: ^5.0.0 + jest-util: ^29.6.3 + p-limit: ^3.1.0 + checksum: 55bc820a70c220a02fec214d5c48d5e0d829549e5c7b9959776b4ca3f76f5ff20c7c8ff816a847822766f1d712477ab3027f7a66ec61bf65de3f852e878b4dfd + languageName: node + linkType: hard + "jest-circus@npm:^29.3.1": version: 29.3.1 resolution: "jest-circus@npm:29.3.1" @@ -21628,6 +22031,34 @@ __metadata: languageName: node linkType: hard +"jest-circus@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-circus@npm:29.6.4" + dependencies: + "@jest/environment": ^29.6.4 + "@jest/expect": ^29.6.4 + "@jest/test-result": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + dedent: ^1.0.0 + is-generator-fn: ^2.0.0 + jest-each: ^29.6.3 + jest-matcher-utils: ^29.6.4 + jest-message-util: ^29.6.3 + jest-runtime: ^29.6.4 + jest-snapshot: ^29.6.4 + jest-util: ^29.6.3 + p-limit: ^3.1.0 + pretty-format: ^29.6.3 + pure-rand: ^6.0.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 31f64ddf6df4aefe30ef5f8de9da137c9cba58ab5e2a25cf749450735088dc88a9974591a4256d481af0fe64608173c921219f9fad9a7dd87cbe47a79e111be8 + languageName: node + linkType: hard + "jest-cli@npm:^29.3.1": version: 29.3.1 resolution: "jest-cli@npm:29.3.1" @@ -21655,6 +22086,33 @@ __metadata: languageName: node linkType: hard +"jest-cli@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-cli@npm:29.6.4" + dependencies: + "@jest/core": ^29.6.4 + "@jest/test-result": ^29.6.4 + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + import-local: ^3.0.2 + jest-config: ^29.6.4 + jest-util: ^29.6.3 + jest-validate: ^29.6.3 + prompts: ^2.0.1 + yargs: ^17.3.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 87a85a27eff0e502717b6ee0ce861d3e50d8c47d7298477f8ca10964b958f06c20241d28f1360ce2a85072763483e4924248106a8ed530ca460a56db3fdfc53e + languageName: node + linkType: hard + "jest-config@npm:^29.3.1": version: 29.3.1 resolution: "jest-config@npm:29.3.1" @@ -21693,6 +22151,44 @@ __metadata: languageName: node linkType: hard +"jest-config@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-config@npm:29.6.4" + dependencies: + "@babel/core": ^7.11.6 + "@jest/test-sequencer": ^29.6.4 + "@jest/types": ^29.6.3 + babel-jest: ^29.6.4 + chalk: ^4.0.0 + ci-info: ^3.2.0 + deepmerge: ^4.2.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-circus: ^29.6.4 + jest-environment-node: ^29.6.4 + jest-get-type: ^29.6.3 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.6.4 + jest-runner: ^29.6.4 + jest-util: ^29.6.3 + jest-validate: ^29.6.3 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^29.6.3 + slash: ^3.0.0 + strip-json-comments: ^3.1.1 + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 177352658774344896df3988dbe892e0b117579f45cc43aebc588493665bf19a557e202f097f5b4a987314ec2d84afa0769299ac6e702c5923d1fd3cfa4692b0 + languageName: node + linkType: hard + "jest-date-mock@npm:1.0.8": version: 1.0.8 resolution: "jest-date-mock@npm:1.0.8" @@ -21748,6 +22244,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-diff@npm:29.6.4" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^29.6.3 + jest-get-type: ^29.6.3 + pretty-format: ^29.6.3 + checksum: e205c45ab6dbcc660dc2a682cddb20f6a3cbbbdecd2821cce2050619f96dbd7560ee25f7f51d42c302596aeaddbea54390b78be3ab639340d24d67e4d270a8b0 + languageName: node + linkType: hard + "jest-docblock@npm:^29.2.0": version: 29.2.0 resolution: "jest-docblock@npm:29.2.0" @@ -21757,6 +22265,15 @@ __metadata: languageName: node linkType: hard +"jest-docblock@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-docblock@npm:29.6.3" + dependencies: + detect-newline: ^3.0.0 + checksum: 6f3213a1e79e7eedafeb462acfa9a41303f9c0167893b140f6818fa16d7eb6bf3f9b9cf4669097ca6b7154847793489ecd6b4f6cfb0e416b88cfa3b4b36715b6 + languageName: node + linkType: hard + "jest-each@npm:^29.3.1": version: 29.3.1 resolution: "jest-each@npm:29.3.1" @@ -21770,6 +22287,19 @@ __metadata: languageName: node linkType: hard +"jest-each@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-each@npm:29.6.3" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + jest-util: ^29.6.3 + pretty-format: ^29.6.3 + checksum: fe06e80b3554e2a8464f5f5c61943e02db1f8a7177139cb55b3201a1d1513cb089d8800401f102729a31bf8dd6f88229044e6088fea9dd5647ed11e841b6b88c + languageName: node + linkType: hard + "jest-environment-jsdom@npm:29.3.1": version: 29.3.1 resolution: "jest-environment-jsdom@npm:29.3.1" @@ -21805,6 +22335,20 @@ __metadata: languageName: node linkType: hard +"jest-environment-node@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-environment-node@npm:29.6.4" + dependencies: + "@jest/environment": ^29.6.4 + "@jest/fake-timers": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.6.3 + jest-util: ^29.6.3 + checksum: 518221505af4bd32c84f2af2c03f9d771de2711bd69fe7723b648fcc2e05d95b4e75f493afa9010209e26a4a3309ebee971f9b18c45b540891771d3b68c3a16e + languageName: node + linkType: hard + "jest-fail-on-console@npm:3.1.1": version: 3.1.1 resolution: "jest-fail-on-console@npm:3.1.1" @@ -21842,6 +22386,13 @@ __metadata: languageName: node linkType: hard +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 88ac9102d4679d768accae29f1e75f592b760b44277df288ad76ce5bf038c3f5ce3719dea8aa0f035dac30e9eb034b848ce716b9183ad7cc222d029f03e92205 + languageName: node + linkType: hard + "jest-haste-map@npm:^29.3.1": version: 29.3.1 resolution: "jest-haste-map@npm:29.3.1" @@ -21865,6 +22416,29 @@ __metadata: languageName: node linkType: hard +"jest-haste-map@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-haste-map@npm:29.6.4" + dependencies: + "@jest/types": ^29.6.3 + "@types/graceful-fs": ^4.1.3 + "@types/node": "*" + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^29.6.3 + jest-util: ^29.6.3 + jest-worker: ^29.6.4 + micromatch: ^4.0.4 + walker: ^1.0.8 + dependenciesMeta: + fsevents: + optional: true + checksum: 4f720fd3813bb38400b7a9a094e55664cbddd907ba1769457ed746f6c870c615167647a5b697a788183d832b1dcb1b66143e52990a6f4403283f6686077fa868 + languageName: node + linkType: hard + "jest-junit@npm:16.0.0": version: 16.0.0 resolution: "jest-junit@npm:16.0.0" @@ -21887,6 +22461,16 @@ __metadata: languageName: node linkType: hard +"jest-leak-detector@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-leak-detector@npm:29.6.3" + dependencies: + jest-get-type: ^29.6.3 + pretty-format: ^29.6.3 + checksum: 27548fcfc7602fe1b88f8600185e35ffff71751f3631e52bbfdfc72776f5a13a430185cf02fc632b41320a74f99ae90e40ce101c8887509f0f919608a7175129 + languageName: node + linkType: hard + "jest-matcher-utils@npm:29.3.1, jest-matcher-utils@npm:^29.3.1": version: 29.3.1 resolution: "jest-matcher-utils@npm:29.3.1" @@ -21899,6 +22483,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-matcher-utils@npm:29.6.4" + dependencies: + chalk: ^4.0.0 + jest-diff: ^29.6.4 + jest-get-type: ^29.6.3 + pretty-format: ^29.6.3 + checksum: 9e17bce282e74bdbba2ce5475c490e0bba4f464cd42132bfc5df0337e0853af4dba925c7f4f61cbb0a4818fa121d28d7ff0196ec8829773a22fce59a822976d2 + languageName: node + linkType: hard + "jest-message-util@npm:^29.3.1": version: 29.3.1 resolution: "jest-message-util@npm:29.3.1" @@ -21916,6 +22512,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-message-util@npm:29.6.3" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.6.3 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.6.3 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 59f5229a06c073a8877ba4d2e304cc07d63b0062bf5764d4bed14364403889e77f1825d1bd9017c19a840847d17dffd414dc06f1fcb537b5f9e03dbc65b84ada + languageName: node + linkType: hard + "jest-mock@npm:^29.3.1": version: 29.3.1 resolution: "jest-mock@npm:29.3.1" @@ -21927,6 +22540,17 @@ __metadata: languageName: node linkType: hard +"jest-mock@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-mock@npm:29.6.3" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-util: ^29.6.3 + checksum: 35772968010c0afb1bb1ef78570b9cbea907c6f967d24b4e95e1a596a1000c63d60e225fb9ddfdd5218674da4aa61d92a09927fc26310cecbbfaa8278d919e32 + languageName: node + linkType: hard + "jest-pnp-resolver@npm:^1.2.2": version: 1.2.2 resolution: "jest-pnp-resolver@npm:1.2.2" @@ -21946,6 +22570,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 0518beeb9bf1228261695e54f0feaad3606df26a19764bc19541e0fc6e2a3737191904607fb72f3f2ce85d9c16b28df79b7b1ec9443aa08c3ef0e9efda6f8f2a + languageName: node + linkType: hard + "jest-resolve-dependencies@npm:^29.3.1": version: 29.3.1 resolution: "jest-resolve-dependencies@npm:29.3.1" @@ -21956,6 +22587,16 @@ __metadata: languageName: node linkType: hard +"jest-resolve-dependencies@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-resolve-dependencies@npm:29.6.4" + dependencies: + jest-regex-util: ^29.6.3 + jest-snapshot: ^29.6.4 + checksum: 34f81d22cbd72203130cc14cbb66d5783d9f59fba4d366b9653f8fb4f6feeaac25d89696f2f77c700659843d5440dc92f58ad443ba05da1da46c39234866d916 + languageName: node + linkType: hard + "jest-resolve@npm:^29.3.1": version: 29.3.1 resolution: "jest-resolve@npm:29.3.1" @@ -21973,6 +22614,23 @@ __metadata: languageName: node linkType: hard +"jest-resolve@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-resolve@npm:29.6.4" + dependencies: + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.4 + jest-pnp-resolver: ^1.2.2 + jest-util: ^29.6.3 + jest-validate: ^29.6.3 + resolve: ^1.20.0 + resolve.exports: ^2.0.0 + slash: ^3.0.0 + checksum: 5f0ef260aec79ef00e16e0ba7b27d527054e1faed08a144279cd191b5c5b71af67c52b9ddfd24aa2f563d254618ce9bf7519809f23fb2abf6c4fa375503caa28 + languageName: node + linkType: hard + "jest-runner@npm:^29.3.1": version: 29.3.1 resolution: "jest-runner@npm:29.3.1" @@ -22002,6 +22660,35 @@ __metadata: languageName: node linkType: hard +"jest-runner@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-runner@npm:29.6.4" + dependencies: + "@jest/console": ^29.6.4 + "@jest/environment": ^29.6.4 + "@jest/test-result": ^29.6.4 + "@jest/transform": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.6.3 + jest-environment-node: ^29.6.4 + jest-haste-map: ^29.6.4 + jest-leak-detector: ^29.6.3 + jest-message-util: ^29.6.3 + jest-resolve: ^29.6.4 + jest-runtime: ^29.6.4 + jest-util: ^29.6.3 + jest-watcher: ^29.6.4 + jest-worker: ^29.6.4 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: ca977dd30262171fe000de8407a3187c16e7057ddf690bcc21068155aacd4824ee927b544e0fa9f2885948b47a5123b472da41e095e3bcbdebb79f1fa2f2fc56 + languageName: node + linkType: hard + "jest-runtime@npm:^29.3.1": version: 29.3.1 resolution: "jest-runtime@npm:29.3.1" @@ -22032,6 +22719,36 @@ __metadata: languageName: node linkType: hard +"jest-runtime@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-runtime@npm:29.6.4" + dependencies: + "@jest/environment": ^29.6.4 + "@jest/fake-timers": ^29.6.4 + "@jest/globals": ^29.6.4 + "@jest/source-map": ^29.6.3 + "@jest/test-result": ^29.6.4 + "@jest/transform": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + cjs-module-lexer: ^1.0.0 + collect-v8-coverage: ^1.0.0 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.4 + jest-message-util: ^29.6.3 + jest-mock: ^29.6.3 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.6.4 + jest-snapshot: ^29.6.4 + jest-util: ^29.6.3 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: 93deacd06f8f2bb808dbfb8acbcbc0b724187b3d3fffafd497a32c939bf385ca21f5a3f03eebd5b958a0e93865d0e68a0db73bd0fe16dafbd5e922558aa7b359 + languageName: node + linkType: hard + "jest-snapshot@npm:^29.3.1": version: 29.3.1 resolution: "jest-snapshot@npm:29.3.1" @@ -22064,6 +22781,34 @@ __metadata: languageName: node linkType: hard +"jest-snapshot@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-snapshot@npm:29.6.4" + dependencies: + "@babel/core": ^7.11.6 + "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-jsx": ^7.7.2 + "@babel/plugin-syntax-typescript": ^7.7.2 + "@babel/types": ^7.3.3 + "@jest/expect-utils": ^29.6.4 + "@jest/transform": ^29.6.4 + "@jest/types": ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + chalk: ^4.0.0 + expect: ^29.6.4 + graceful-fs: ^4.2.9 + jest-diff: ^29.6.4 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.6.4 + jest-message-util: ^29.6.3 + jest-util: ^29.6.3 + natural-compare: ^1.4.0 + pretty-format: ^29.6.3 + semver: ^7.5.3 + checksum: 0c9b5ec640457fb780ac6c9b6caa814436e9e16bf744772eee3bfd055ae5f7a3085a6a09b2f30910e31915dafc3955d92357cc98189e4d5dcb417b5fdafda6e3 + languageName: node + linkType: hard + "jest-util@npm:^29.0.0, jest-util@npm:^29.3.1": version: 29.3.1 resolution: "jest-util@npm:29.3.1" @@ -22106,6 +22851,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-util@npm:29.6.3" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 7bf3ba3ac67ac6ceff7d8fdd23a86768e23ddd9133ecd9140ef87cc0c28708effabaf67a6cd45cd9d90a63d645a522ed0825d09ee59ac4c03b9c473b1fef4c7c + languageName: node + linkType: hard + "jest-validate@npm:^29.3.1": version: 29.3.1 resolution: "jest-validate@npm:29.3.1" @@ -22120,6 +22879,20 @@ __metadata: languageName: node linkType: hard +"jest-validate@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-validate@npm:29.6.3" + dependencies: + "@jest/types": ^29.6.3 + camelcase: ^6.2.0 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + leven: ^3.1.0 + pretty-format: ^29.6.3 + checksum: caa489ed11080441c636b8035ab71bafbdc0c052b1e452855e4d2dd24ac15e497710a270ea6fc5ef8926b22c1ce4d6e07ec2dc193f0810cff5851d7a2222c045 + languageName: node + linkType: hard + "jest-watcher@npm:^29.3.1": version: 29.3.1 resolution: "jest-watcher@npm:29.3.1" @@ -22136,6 +22909,22 @@ __metadata: languageName: node linkType: hard +"jest-watcher@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-watcher@npm:29.6.4" + dependencies: + "@jest/test-result": ^29.6.4 + "@jest/types": ^29.6.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.13.1 + jest-util: ^29.6.3 + string-length: ^4.0.1 + checksum: 13c0f96f7e9212e4f3ef2daf3e787045bdcec414061bf286eca934c7f4083fb04d38df9ced9c0edfbe15f3521ca581eb2ed6108c338a0db1f3e1def65687992f + languageName: node + linkType: hard + "jest-worker@npm:^26.2.1": version: 26.6.2 resolution: "jest-worker@npm:26.6.2" @@ -22205,6 +22994,18 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-worker@npm:29.6.4" + dependencies: + "@types/node": "*" + jest-util: ^29.6.3 + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 05d19a5759ebfeb964036065be55ad8d8e8ddffa85d9b3a4c0b95765695efb1d8226ec824a4d8e660c38cda3389bfeb98d819f47232acf9fb0e79f553b7c0a76 + languageName: node + linkType: hard + "jest@npm:29.3.1": version: 29.3.1 resolution: "jest@npm:29.3.1" @@ -22224,6 +23025,25 @@ __metadata: languageName: node linkType: hard +"jest@npm:^29.6.4": + version: 29.6.4 + resolution: "jest@npm:29.6.4" + dependencies: + "@jest/core": ^29.6.4 + "@jest/types": ^29.6.3 + import-local: ^3.0.2 + jest-cli: ^29.6.4 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: ba28ca7a86d029bcd742bb254c0c8d0119c1e002ddae128ff6409ebabc0b29c36f69dbf3fdd326aff16e7b2500c9a918bbc6a9a5db4d966e035127242239439f + languageName: node + linkType: hard + "jiti@npm:^1.18.2": version: 1.19.1 resolution: "jiti@npm:1.19.1" @@ -26311,6 +27131,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.6.3": + version: 29.6.3 + resolution: "pretty-format@npm:29.6.3" + dependencies: + "@jest/schemas": ^29.6.3 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: 4e1c0db48e65571c22e80ff92123925ff8b3a2a89b71c3a1683cfde711004d492de32fe60c6bc10eea8bf6c678e5cbe544ac6c56cb8096e1eb7caf856928b1c4 + languageName: node + linkType: hard + "pretty-hrtime@npm:^1.0.3": version: 1.0.3 resolution: "pretty-hrtime@npm:1.0.3" @@ -26615,6 +27446,13 @@ __metadata: languageName: node linkType: hard +"pure-rand@npm:^6.0.0": + version: 6.0.3 + resolution: "pure-rand@npm:6.0.3" + checksum: d08701cfd1528c5f9cdca996776c498c92767722561f9b8f9e62645d5025c8a3bf60b90f76f262aaab124e6bb1d58e1b0850722dbca2846a19b708801956e56b + languageName: node + linkType: hard + "q@npm:^1.5.1": version: 1.5.1 resolution: "q@npm:1.5.1" @@ -28705,6 +29543,13 @@ __metadata: languageName: node linkType: hard +"resolve.exports@npm:^2.0.0": + version: 2.0.2 + resolution: "resolve.exports@npm:2.0.2" + checksum: 1c7778ca1b86a94f8ab4055d196c7d87d1874b96df4d7c3e67bbf793140f0717fd506dcafd62785b079cd6086b9264424ad634fb904409764c3509c3df1653f2 + languageName: node + linkType: hard + "resolve@npm:^1.1.6, resolve@npm:^1.22.1": version: 1.22.1 resolution: "resolve@npm:1.22.1" @@ -29244,7 +30089,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.1, semver@npm:^7.5.3": +"semver@npm:7.5.4, semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.1, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -33119,6 +33964,16 @@ __metadata: languageName: node linkType: hard +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" + dependencies: + imurmurhash: ^0.1.4 + signal-exit: ^3.0.7 + checksum: 5da60bd4eeeb935eec97ead3df6e28e5917a6bd317478e4a85a5285e8480b8ed96032bbcc6ecd07b236142a24f3ca871c924ec4a6575e623ec1b11bf8c1c253c + languageName: node + linkType: hard + "write-file-atomic@npm:^5.0.1": version: 5.0.1 resolution: "write-file-atomic@npm:5.0.1"