Skip to content

Commit

Permalink
Bugfix/metric-loading-loop (opensearch-project#1309)
Browse files Browse the repository at this point in the history
* Metric workflow fixes

* Visualization action-menu correction for OSD Dashboards context and Menu Explorer context
* Visualization of Promql metric navigate to Metric Explorer on "Edit"
* Metric Explorer correct loading of metric by URL Id

---------

Signed-off-by: Peter Fitzgibbons <[email protected]>
  • Loading branch information
pjfitzgibbons authored Dec 19, 2023
1 parent d16f2b2 commit fd55726
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 50 deletions.
44 changes: 27 additions & 17 deletions public/components/custom_panels/helpers/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,25 +259,34 @@ const dynamicLayoutFromQueryData = (queryData) => {
};
};

const createCatalogVisualizationMetaData = (
catalogSource: string,
visualizationQuery: string,
visualizationType: string,
visualizationTimeField: string,
queryData: object
) => {
const createCatalogVisualizationMetaData = ({
catalogSource,
query,
type,
subType,
timeField,
queryData,
}: {
catalogSource: string;
query: string;
type: string;
subType: string;
timeField: string;
queryData: object;
}) => {
return {
name: catalogSource,
description: '',
query: visualizationQuery,
type: visualizationType,
query,
type,
subType,
selected_date_range: {
start: 'now/y',
end: 'now',
text: '',
},
selected_timestamp: {
name: visualizationTimeField,
name: timeField,
type: 'timestamp',
},
selected_fields: {
Expand Down Expand Up @@ -332,6 +341,7 @@ export const renderCatalogVisualization = async ({

const visualizationType = 'line';
const visualizationTimeField = '@timestamp';
const visualizationSubType = visualization.subType;

const visualizationQuery = updateCatalogVisualizationQuery({
...visualization.queryMetaData,
Expand All @@ -357,15 +367,15 @@ export const renderCatalogVisualization = async ({
);
setVisualizationData(queryData);

const visualizationMetaData = createCatalogVisualizationMetaData(
const visualizationMetaData = createCatalogVisualizationMetaData({
catalogSource,
visualizationQuery,
visualizationType,
visualizationTimeField,
queryData
);
query: visualizationQuery,
type: visualizationType,
subType: visualization.subType,
timeField: visualizationTimeField,
queryData,
});

console.log('renderCatalogVisualization', { visualizationMetaData });
setVisualizationMetaData(visualizationMetaData);
} catch (error) {
setIsError({ error });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ import './visualization_container.scss';
import { VizContainerError } from '../../../../../common/types/custom_panels';
import { metricQuerySelector } from '../../../metrics/redux/slices/metrics_slice';
import { coreRefs } from '../../../../framework/core_refs';
import { PROMQL_METRIC_SUBTYPE } from '../../../../../common/constants/shared';
import {
observabilityMetricsID,
PROMQL_METRIC_SUBTYPE,
} from '../../../../../common/constants/shared';

/*
* Visualization container - This module is a placeholder to add visualizations in react-grid-layout
Expand Down Expand Up @@ -78,6 +81,7 @@ interface Props {
removeVisualization?: (visualizationId: string) => void;
catalogVisualization?: boolean;
inlineEditor?: JSX.Element;
actionMenuType?: string;
}

export const VisualizationContainer = ({
Expand All @@ -98,6 +102,7 @@ export const VisualizationContainer = ({
removeVisualization,
catalogVisualization,
inlineEditor,
actionMenuType,
}: Props) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [visualizationTitle, setVisualizationTitle] = useState('');
Expand Down Expand Up @@ -175,7 +180,11 @@ export const VisualizationContainer = ({
disabled={editMode}
onClick={() => {
closeActionsMenu();
onEditClick(savedVisualizationId);
if (visualizationMetaData?.subType === PROMQL_METRIC_SUBTYPE) {
window.location.assign(`${observabilityMetricsID}#/${savedVisualizationId}`);
} else {
onEditClick(savedVisualizationId);
}
}}
>
Edit
Expand Down Expand Up @@ -217,7 +226,10 @@ export const VisualizationContainer = ({
</EuiContextMenuItem>,
];

if (visualizationMetaData?.subType === PROMQL_METRIC_SUBTYPE) {
if (
visualizationMetaData?.subType === PROMQL_METRIC_SUBTYPE &&
actionMenuType === 'metricsGrid'
) {
popoverPanel = [showPPLQueryPanel];
} else if (usedInNotebooks) {
popoverPanel = [popoverPanel[0]];
Expand Down
55 changes: 30 additions & 25 deletions public/components/metrics/redux/slices/metrics_slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { keyBy, mergeWith, pick, sortBy, merge } from 'lodash';
import { createSlice } from '@reduxjs/toolkit';
import { keyBy, mergeWith, pick, sortBy } from 'lodash';
import { ouiPaletteColorBlindBehindText } from '@elastic/eui';
import {
OBSERVABILITY_CUSTOM_METRIC,
Expand All @@ -18,7 +18,7 @@ import { ObservabilitySavedVisualization } from '../../../../services/saved_obje
import { pplServiceRequestor } from '../../helpers/utils';
import { coreRefs } from '../../../../framework/core_refs';
import { PPL_METRIC_SUBTYPE, PROMQL_METRIC_SUBTYPE } from '../../../../../common/constants/shared';
import { getOSDHttp, getPPLService } from '../../../../../common/utils';
import { getPPLService } from '../../../../../common/utils';

export interface IconAttributes {
color: string;
Expand All @@ -38,6 +38,14 @@ const coloredIconsFrom = (dataSources: string[]): { [dataSource: string]: IconAt
return Object.fromEntries(keyedIcons);
};

export interface DateSpanFilter {
start: string;
end: string;
span: number;
resolution: string;
recentlyUsedRanges: string[];
}

const initialState = {
metrics: {},
selectedIds: [],
Expand Down Expand Up @@ -66,8 +74,13 @@ const mergeMetricCustomizer = function (objValue, srcValue) {
: srcValue.availableAttributes,
};
};
export const mergeMetrics = (newMetricMap) => (dispatch, getState) => {
const { metrics } = getState().metrics;
const modifiableMetricsMap = { ...metrics };

const now = () => new Date().getMilliseconds();
const mergedMetrics = mergeWith(modifiableMetricsMap, newMetricMap, mergeMetricCustomizer);
dispatch(setMetrics(mergedMetrics));
};

export const loadMetrics = () => async (dispatch) => {
const pplService = getPPLService();
Expand All @@ -81,15 +94,15 @@ export const loadMetrics = () => async (dispatch) => {
setDataSourceIcons(coloredIconsFrom([OBSERVABILITY_CUSTOM_METRIC, ...remoteDataSources]))
);

const remoteDataRequests = fetchRemoteMetrics(remoteDataSources);
const remoteDataRequests = await fetchRemoteMetrics(remoteDataSources);
const metricsResultSet = await Promise.all([customDataRequest, ...remoteDataRequests]);
const metricsResult = metricsResultSet.flat();

const metricsMapById = keyBy(metricsResult.flat(), 'id');
await dispatch(mergeMetrics(metricsMapById));
dispatch(mergeMetrics(metricsMapById));

const sortedIds = sortBy(metricsResult, 'catalog', 'id').map((m) => m.id);
await dispatch(setSortedIds(sortedIds));
dispatch(setSortedIds(sortedIds));
};

const fetchCustomMetrics = async () => {
Expand Down Expand Up @@ -150,17 +163,9 @@ export const metricSlice = createSlice({
name: REDUX_SLICE_METRICS,
initialState,
reducers: {
mergeMetrics: (state, { payload }) => {
const { metrics } = state;
const modifiableMetricsMap = { ...metrics };

const mergedMetrics = mergeWith(modifiableMetricsMap, payload, mergeMetricCustomizer);
state.metrics = mergedMetrics;
setMetrics: (state, { payload }) => {
state.metrics = payload;
},

// setMetrics: (state, { payload }) => {
// state.metrics = payload;
// },
setMetric: (state, { payload }) => {
state.metrics[payload.id] = payload;
},
Expand Down Expand Up @@ -202,15 +207,19 @@ export const metricSlice = createSlice({
setDataSourceIcons: (state, { payload }) => {
state.dataSourceIcons = payload;
},
setDateSpan: (state, { payload }) => {
state.dateSpanFilter = { ...state.dateSpanFilter, ...payload };
},
setRefresh: (state) => {
state.refresh = Date.now();
},
},
});

export const {
setMetrics,
deSelectMetric,
clearSelectedMetrics,

mergeMetrics,
selectMetric,
moveMetric,
setSearch,
setDateSpan,
Expand All @@ -222,7 +231,7 @@ export const {

/** private actions */

const { selectMetric, setMetric, setSortedIds } = metricSlice.actions;
const { setMetrics, setMetric, setSortedIds } = metricSlice.actions;

const getAvailableAttributes = (id, metricIndex) => async (dispatch, getState) => {
const { toasts } = coreRefs;
Expand Down Expand Up @@ -295,16 +304,12 @@ export const availableMetricsSelector = (state) => {
export const selectedMetricsSelector = (state) =>
pick(state.metrics.metrics, state.metrics.selectedIds) ?? {};

export const selectedMetricByIdSelector = (id) => (state) => state.metrics.metrics[id];

export const selectedMetricsIdsSelector = (state) => state.metrics.selectedIds ?? [];

export const searchSelector = (state) => state.metrics.search;

export const metricIconsSelector = (state) => state.metrics.dataSourceIcons;

export const metricsLayoutSelector = (state) => state.metrics.metricsLayout;

export const dateSpanFilterSelector = (state) => state.metrics.dateSpanFilter;

export const refreshSelector = (state) => state.metrics.refresh;
Expand Down
8 changes: 5 additions & 3 deletions public/components/metrics/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ export const Sidebar = ({

useEffect(() => {
if (additionalMetric) {
dispatch(clearSelectedMetrics());
dispatch(addSelectedMetric(additionalMetric));
(async function () {
await dispatch(clearSelectedMetrics());
await dispatch(addSelectedMetric(additionalMetric));
})();
}
}, [additionalMetric]);
}, [additionalMetric?.id]);

const selectedMetricsList = useMemo(() => {
return selectedMetricsIds.map((id) => selectedMetrics[id]).filter((m) => m); // filter away null entries
Expand Down
16 changes: 15 additions & 1 deletion public/components/metrics/view/metrics_grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import React, { useEffect, useMemo } from 'react';
import { EuiDragDropContext, EuiDraggable, EuiDroppable } from '@elastic/eui';
import { EuiContextMenuItem, EuiDragDropContext, EuiDraggable, EuiDroppable } from '@elastic/eui';
import { useObservable } from 'react-use';
import { connect } from 'react-redux';
import { CoreStart } from '../../../../../../src/core/public';
Expand Down Expand Up @@ -53,6 +53,19 @@ const visualizationFromMetric = (metric, dateSpanFilter): SavedVisualizationType
},
});

const promQLActionMenu = [
<EuiContextMenuItem
data-test-subj="showCatalogPPLQuery"
key="view_query"
onClick={() => {
closeActionsMenu();
showModal('catalogModal');
}}
>
View query
</EuiContextMenuItem>,
];

const navigateToEventExplorerVisualization = (savedVisualizationId: string) => {
window.location.assign(`${observabilityLogsID}#/explorer/${savedVisualizationId}`);
};
Expand Down Expand Up @@ -80,6 +93,7 @@ export const InnerGridVisualization = ({ id, idx, dateSpanFilter, metric, refres
inlineEditor={
metric.subType === PROMQL_METRIC_SUBTYPE && <MetricsEditInline visualization={metric} />
}
actionMenuType="metricsGrid"
/>
</EuiDraggable>
);
Expand Down
2 changes: 1 addition & 1 deletion public/services/requests/ppl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { PPL_BASE, PPL_SEARCH } from '../../../common/constants/shared';
/* eslint-disable import/no-default-export */
export default class PPLService {
private http;

constructor(http: CoreStart['http']) {
this.http = http;
}
Expand All @@ -20,7 +21,6 @@ export default class PPLService {
},
errorHandler?: (error: any) => void
) => {
console.log('real fetch');
return this.http
.post(`${PPL_BASE}${PPL_SEARCH}`, {
body: JSON.stringify(params),
Expand Down

0 comments on commit fd55726

Please sign in to comment.