diff --git a/dashboards-observability/common/types/explorer.ts b/dashboards-observability/common/types/explorer.ts index a734d7150..dade11d67 100644 --- a/dashboards-observability/common/types/explorer.ts +++ b/dashboards-observability/common/types/explorer.ts @@ -5,6 +5,7 @@ import { History } from 'history'; import Plotly from 'plotly.js-dist'; +import { QueryManager } from 'common/query_manager'; import { RAW_QUERY, SELECTED_FIELDS, @@ -16,12 +17,18 @@ import { SELECTED_TIMESTAMP, SELECTED_DATE_RANGE, } from '../constants/explorer'; -import { CoreStart, HttpSetup, HttpStart, NotificationsStart } from '../../../../src/core/public'; +import { + CoreStart, + CoreSetup, + HttpSetup, + HttpStart, + NotificationsStart, +} from '../../../../src/core/public'; import SavedObjects from '../../public/services/saved_objects/event_analytics/saved_objects'; import TimestampUtils from '../../public/services/timestamp/timestamp'; import PPLService from '../../public/services/requests/ppl'; import DSLService from '../../public/services/requests/dsl'; - +import { SavedObjectsStart } from '../../../../src/core/public/saved_objects'; export interface IQueryTab { id: string; name: React.ReactNode | string; @@ -34,6 +41,13 @@ export interface IField { label?: string; } +export interface ExplorerFields { + availableFields: IField[]; + queriedFields: IField[]; + selectedFields: IField[]; + unselectedFields: IField[]; +} + export interface ITabQueryResults { [tabId: string]: any; } @@ -83,6 +97,7 @@ export interface ILogExplorerProps { ) => void; savedObjectId: string; getExistingEmptyTab: (params: EmptyTabParams) => string; + qm: QueryManager; } export interface IExplorerProps { @@ -113,6 +128,7 @@ export interface IExplorerProps { appBaseQuery?: string; callback?: any; callbackInApp?: any; + qm: QueryManager; } export interface SavedQuery { @@ -283,3 +299,26 @@ export interface ConfigList { breakdowns?: ConfigListEntry[] | HistogramConfigList[]; span?: DimensionSpan; } + +export interface Breadcrumbs { + text: string; + href: string; +} + +export interface EventAnalyticsProps { + chrome: CoreSetup; + parentBreadcrumbs: Breadcrumbs[]; + pplService: any; + dslService: any; + savedObjects: SavedObjectsStart; + timestampUtils: TimestampUtils; + http: HttpStart; + notifications: NotificationsStart; + qm: QueryManager; +} + +export interface DataConfigPanelProps { + fieldOptionList: IField[]; + visualizations: IVisualizationContainerProps; + qm?: QueryManager; +} diff --git a/dashboards-observability/public/components/app.tsx b/dashboards-observability/public/components/app.tsx index b4d164331..6e69cd69d 100644 --- a/dashboards-observability/public/components/app.tsx +++ b/dashboards-observability/public/components/app.tsx @@ -7,6 +7,7 @@ import { I18nProvider } from '@osd/i18n/react'; import React from 'react'; import { Provider } from 'react-redux'; import { HashRouter, Route, Switch } from 'react-router-dom'; +import { QueryManager } from 'common/query_manager'; import { CoreStart } from '../../../../src/core/public'; import { observabilityID, observabilityTitle } from '../../common/constants/shared'; import store from '../framework/redux/store'; @@ -24,6 +25,7 @@ interface ObservabilityAppDeps { dslService: any; savedObjects: any; timestampUtils: any; + qm: QueryManager; } // for cypress to test redux store @@ -38,6 +40,7 @@ export const App = ({ dslService, savedObjects, timestampUtils, + qm, }: ObservabilityAppDeps) => { const { chrome, http, notifications } = CoreStartProp; const parentBreadcrumb = { @@ -130,6 +133,7 @@ export const App = ({ timestampUtils={timestampUtils} http={http} notifications={notifications} + qm={qm} {...props} /> ); diff --git a/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx b/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx index dca34b9d3..dc2fe3b53 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx @@ -78,7 +78,6 @@ import { getVizContainerProps } from '../../visualizations/charts/helpers'; import { parseGetSuggestions, onItemSelect } from '../../common/search/autocomplete_logic'; import { formatError } from '../utils'; import { sleep } from '../../common/live_tail/live_tail_button'; -import { QueryManager } from '../../../../common/query_manager/ppl_query_manager'; const TYPE_TAB_MAPPING = { [SAVED_QUERY]: TAB_EVENT_ID, @@ -107,6 +106,7 @@ export const Explorer = ({ setEndTime, callback, callbackInApp, + qm, }: IExplorerProps) => { const dispatch = useDispatch(); const requestParams = { tabId }; @@ -143,7 +143,7 @@ export const Explorer = ({ const [browserTabFocus, setBrowserTabFocus] = useState(true); const [liveTimestamp, setLiveTimestamp] = useState(DATE_PICKER_FORMAT); const [triggerAvailability, setTriggerAvailability] = useState(false); - const [isValidDataConfigOptionSelected, setIsValidDataConfigOptionSelected] = useState( + const [isValidDataConfigOptionSelected, setIsValidDataConfigOptionSelected] = useState( false ); @@ -631,7 +631,7 @@ export const Explorer = ({ 0 )} showResetButton={false} - onResetQuery={() => { }} + onResetQuery={() => {}} /> @@ -672,7 +672,7 @@ export const Explorer = ({ { }} + onResetQuery={() => {}} /> since {liveTimestamp} @@ -746,7 +746,7 @@ export const Explorer = ({ } }; - const changeIsValidConfigOptionState = (isValidConfig: Boolean) => + const changeIsValidConfigOptionState = (isValidConfig: boolean) => setIsValidDataConfigOptionSelected(isValidConfig); const getExplorerVis = () => { @@ -764,6 +764,7 @@ export const Explorer = ({ handleOverrideTimestamp={handleOverrideTimestamp} callback={callbackForConfig} changeIsValidConfigOptionState={changeIsValidConfigOptionState} + qm={qm} /> ); }; @@ -841,7 +842,6 @@ export const Explorer = ({ if (selectedContentTabId === TAB_CHART_ID) { // parse stats section on every search - const qm = new QueryManager(); const statsTokens = qm.queryParser().parse(tempQuery).getStats(); const timeUnitValue = TIME_INTERVAL_OPTIONS.find( (time_unit) => time_unit.value === statsTokens.groupby?.span.span_expression.time_unit @@ -849,22 +849,22 @@ export const Explorer = ({ const span = statsTokens.groupby?.span !== null ? { - time_field: [ - { - name: statsTokens.groupby?.span.span_expression.field, - type: 'timestamp', - label: statsTokens.groupby?.span.span_expression.field, - }, - ], - unit: [ - { - text: timeUnitValue, - value: statsTokens.groupby?.span.span_expression.time_unit, - label: timeUnitValue, - }, - ], - interval: statsTokens.groupby?.span.span_expression.literal_value, - } + time_field: [ + { + name: statsTokens.groupby?.span.span_expression.field, + type: 'timestamp', + label: statsTokens.groupby?.span.span_expression.field, + }, + ], + unit: [ + { + text: timeUnitValue, + value: statsTokens.groupby?.span.span_expression.time_unit, + label: timeUnitValue, + }, + ], + interval: statsTokens.groupby?.span.span_expression.literal_value, + } : undefined; await dispatch( diff --git a/dashboards-observability/public/components/event_analytics/explorer/log_explorer.tsx b/dashboards-observability/public/components/event_analytics/explorer/log_explorer.tsx index 53bd15be4..1d84a5815 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/log_explorer.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/log_explorer.tsx @@ -49,6 +49,7 @@ export const LogExplorer = ({ history, notifications, http, + qm, }: ILogExplorerProps) => { const dispatch = useDispatch(); const tabIds = useSelector(selectQueryTabs).queryTabIds.filter( @@ -184,6 +185,7 @@ export const LogExplorer = ({ curSelectedTabId={curSelectedTabIdRef} http={http} searchBarConfigs={searchBarConfigs} + qm={qm} /> ), diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx index adf8a6b51..53f16bff5 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx @@ -30,9 +30,8 @@ import { } from '../../../../../../../../common/constants/explorer'; import { ButtonGroupItem } from './config_button_group'; import { visChartTypes } from '../../../../../../../../common/constants/shared'; -import { ConfigList } from '../../../../../../../../common/types/explorer'; +import { ConfigList, DataConfigPanelProps } from '../../../../../../../../common/types/explorer'; import { TabContext } from '../../../../../hooks'; -import { QueryManager } from '../../../../../../../../common/query_manager'; import { composeAggregations } from '../../../../../../../../common/query_manager/utils'; const initialDimensionEntry = { @@ -47,7 +46,11 @@ const initialMetricEntry = { aggregation: 'count', }; -export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => { +export const DataConfigPanelItem = ({ + fieldOptionList, + visualizations, + qm, +}: DataConfigPanelProps) => { const dispatch = useDispatch(); const { tabId, handleQuerySearch, handleQueryChange, setTempQuery, fetchData } = useContext( TabContext @@ -120,7 +123,6 @@ export const DataConfigPanelItem = ({ fieldOptionList, visualizations }: any) => }; const updateChart = (updatedConfigList = configList) => { - const qm = new QueryManager(); const statsTokens = qm.queryParser().parse(data.query.rawQuery).getStats(); const newQuery = qm .queryBuilder() diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx index 6f9bb5388..d5ac25e73 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx @@ -15,20 +15,27 @@ import { EuiText, } from '@elastic/eui'; import { batch, useDispatch, useSelector } from 'react-redux'; +import { cloneDeep } from 'lodash'; import { AVAILABLE_FIELDS, SELECTED_FIELDS, } from '../../../../../../../../common/constants/explorer'; -import { ConfigList, ConfigListEntry } from '../../../../../../../../common/types/explorer'; +import { + ConfigList, + ConfigListEntry, + DataConfigPanelProps, +} from '../../../../../../../../common/types/explorer'; import { TabContext } from '../../../../../hooks'; import { selectFields, sortFields, updateFields, } from '../../../../../../event_analytics/redux/slices/field_slice'; -import { cloneDeep } from 'lodash'; -export const LogsViewConfigPanelItem = ({ fieldOptionList, visualizations }: any) => { +export const LogsViewConfigPanelItem = ({ + fieldOptionList, + visualizations, +}: DataConfigPanelProps) => { const dispatch = useDispatch(); const { tabId, curVisId, changeVisualizationConfig } = useContext(TabContext); const explorerFields = useSelector(selectFields)[tabId]; @@ -159,7 +166,7 @@ export const LogsViewConfigPanelItem = ({ fieldOptionList, visualizations }: any }; const getLogsViewUI = () => { - let list = configList.dimensions ? configList.dimensions : []; + const list = configList.dimensions ? configList.dimensions : []; const listUI = list.map((field, index) => ( { +export const TreemapConfigPanelItem = ({ + fieldOptionList, + visualizations, + qm, +}: DataConfigPanelProps) => { const dispatch = useDispatch(); const { tabId, curVisId, changeVisualizationConfig, fetchData, handleQueryChange } = useContext< any @@ -51,7 +55,7 @@ export const TreemapConfigPanelItem = ({ fieldOptionList, visualizations, tabID }, [userConfigs?.dataConfig, visualizations.vis.name]); const updateList = (configName: string, fieldName: string, value: string | any[]) => { - let list = { ...configList }; + const list = { ...configList }; let listItem = { ...list[configName][0] }; const newField = { @@ -68,7 +72,6 @@ export const TreemapConfigPanelItem = ({ fieldOptionList, visualizations, tabID }; const updateChart = (updatedConfigList = configList) => { - const qm = new QueryManager(); const statsTokens = qm.queryParser().parse(data.query.rawQuery).getStats(); const newQuery = qm .queryBuilder() @@ -103,7 +106,7 @@ export const TreemapConfigPanelItem = ({ fieldOptionList, visualizations, tabID const getOptionsAvailable = (sectionName: string) => { const { dimensions, metrics } = configList; - let selectedFields = {}; + const selectedFields = {}; let allSelectedFields = []; for (const key in configList) { diff --git a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx index 2e51c1a7e..17d817bc3 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx @@ -9,8 +9,14 @@ import { isEmpty } from 'lodash'; import React, { useContext } from 'react'; import { EuiPanel, EuiResizableContainer, EuiSpacer } from '@elastic/eui'; +import { QueryManager } from 'common/query_manager'; import { RAW_QUERY, SELECTED_TIMESTAMP } from '../../../../../common/constants/explorer'; -import { IField, IQuery, IVisualizationContainerProps } from '../../../../../common/types/explorer'; +import { + IField, + IQuery, + IVisualizationContainerProps, + ExplorerFields, +} from '../../../../../common/types/explorer'; import { WorkspacePanel } from './workspace_panel'; import { ConfigPanel } from './config_panel'; import { Sidebar } from '../sidebar'; @@ -19,19 +25,21 @@ import { TabContext } from '../../hooks'; import { PPL_STATS_REGEX, visChartTypes } from '../../../../../common/constants/shared'; import { TreemapConfigPanelItem } from './config_panel/config_panes/config_controls/treemap_config_panel_item'; import { LogsViewConfigPanelItem } from './config_panel/config_panes/config_controls/logs_view_config_panel_item'; + interface IExplorerVisualizationsProps { query: IQuery; curVisId: string; setCurVisId: (visId: string) => void; explorerVis: any; - explorerFields: IField[]; + explorerFields: ExplorerFields; explorerData: any; handleAddField: (field: IField) => void; handleRemoveField: (field: IField) => void; visualizations: IVisualizationContainerProps; handleOverrideTimestamp: (field: IField) => void; callback?: any; - changeIsValidConfigOptionState: (isValidConfigOptionSelected: Boolean) => void; + changeIsValidConfigOptionState: (isValidConfigOptionSelected: boolean) => void; + qm: QueryManager; } export const ExplorerVisualizations = ({ @@ -47,15 +55,15 @@ export const ExplorerVisualizations = ({ handleOverrideTimestamp, callback, changeIsValidConfigOptionState, + qm, }: IExplorerVisualizationsProps) => { const { tabId } = useContext(TabContext); const { data, vis } = visualizations; const { data: vizData = {}, metadata: { fields = [] } = {} } = data?.rawVizData; - - const fieldOptionList = explorerFields.availableFields.map((field) => { - // const fieldOptionList = fields.map((field) => { - return { ...field, label: field.name }; - }); + const fieldOptionList = explorerFields.availableFields.map((field) => ({ + ...field, + label: field.name, + })); const renderDataConfigContainer = () => { switch (curVisId) { @@ -64,7 +72,7 @@ export const ExplorerVisualizations = ({ ); case visChartTypes.LogsView: @@ -72,7 +80,6 @@ export const ExplorerVisualizations = ({ ); default: @@ -80,7 +87,7 @@ export const ExplorerVisualizations = ({ ); } diff --git a/dashboards-observability/public/components/event_analytics/index.tsx b/dashboards-observability/public/components/event_analytics/index.tsx index edac5e494..42265ba4f 100644 --- a/dashboards-observability/public/components/event_analytics/index.tsx +++ b/dashboards-observability/public/components/event_analytics/index.tsx @@ -5,7 +5,7 @@ import { EuiGlobalToastList } from '@elastic/eui'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; -import { EmptyTabParams } from 'common/types/explorer'; +import { EmptyTabParams, EventAnalyticsProps } from 'common/types/explorer'; import { isEmpty } from 'lodash'; import React, { ReactChild, useState } from 'react'; import { HashRouter, Route, Switch, useHistory } from 'react-router-dom'; @@ -23,8 +23,9 @@ export const EventAnalytics = ({ timestampUtils, http, notifications, + qm, ...props -}: any) => { +}: EventAnalyticsProps) => { const history = useHistory(); const [toasts, setToasts] = useState([]); @@ -84,6 +85,7 @@ export const EventAnalytics = ({ getExistingEmptyTab={getExistingEmptyTab} history={history} notifications={notifications} + qm={qm} /> ); }} diff --git a/dashboards-observability/public/components/index.tsx b/dashboards-observability/public/components/index.tsx index 267cb6b5d..be4f1a040 100644 --- a/dashboards-observability/public/components/index.tsx +++ b/dashboards-observability/public/components/index.tsx @@ -5,6 +5,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { QueryManager } from 'common/query_manager'; import { AppMountParameters, CoreStart } from '../../../../src/core/public'; import { AppPluginStartDependencies } from '../types'; import { App } from './app'; @@ -16,7 +17,8 @@ export const Observability = ( pplService: any, dslService: any, savedObjects: any, - timestampUtils: any + timestampUtils: any, + qm: QueryManager ) => { ReactDOM.render( , AppMountParametersProp.element ); diff --git a/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts b/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts index 48124408d..e23968693 100644 --- a/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts +++ b/dashboards-observability/public/components/visualizations/charts/helpers/viz_types.ts @@ -44,12 +44,12 @@ const initialEntryTreemap = { label: '', name: '' }; const getDefaultXYAxisLabels = (vizFields: IField[], visName: string) => { if (isEmpty(vizFields)) return {}; - const vizFieldsWithLabel: { [key: string]: string }[] = vizFields.map((vizField) => ({ + const vizFieldsWithLabel: Array<{ [key: string]: string }> = vizFields.map((vizField) => ({ ...vizField, label: vizField.name, })); - const mapXaxis = (): { [key: string]: string }[] => { + const mapXaxis = (): Array<{ [key: string]: string }> => { const xaxis = vizFieldsWithLabel.filter((field) => field.type === 'timestamp'); return visName === visChartTypes.Line ? xaxis.length === 0 @@ -58,7 +58,7 @@ const getDefaultXYAxisLabels = (vizFields: IField[], visName: string) => { : [vizFieldsWithLabel[vizFieldsWithLabel.length - 1]]; }; - const mapYaxis = (): { [key: string]: string }[] => + const mapYaxis = (): Array<{ [key: string]: string }> => visName === visChartTypes.Line ? vizFieldsWithLabel.filter((field) => field.type !== 'timestamp') : take( diff --git a/dashboards-observability/public/plugin.ts b/dashboards-observability/public/plugin.ts index 4c3b7f7a2..a14131546 100644 --- a/dashboards-observability/public/plugin.ts +++ b/dashboards-observability/public/plugin.ts @@ -17,7 +17,7 @@ import { AppPluginStartDependencies, ObservabilitySetup, ObservabilityStart } fr import { convertLegacyNotebooksUrl } from './components/notebooks/components/helpers/legacy_route_helpers'; import { convertLegacyTraceAnalyticsUrl } from './components/trace_analytics/components/common/legacy_route_helpers'; import { uiSettingsService } from '../common/utils'; - +import { QueryManager } from '../common/query_manager'; export class ObservabilityPlugin implements Plugin { public setup(core: CoreSetup): ObservabilitySetup { uiSettingsService.init(core.uiSettings, core.notifications); @@ -48,6 +48,7 @@ export class ObservabilityPlugin implements Plugin