diff --git a/common/types/metrics.ts b/common/types/metrics.ts index 2f9b00e2c..c2b7dd3db 100644 --- a/common/types/metrics.ts +++ b/common/types/metrics.ts @@ -16,5 +16,6 @@ export interface MetricType extends VisualizationType { type: 'savedCustomMetric' | 'prometheusMetric'; aggregation: string; attributesGroupBy: string[]; + availableAttributes?: string[]; }; } diff --git a/public/components/custom_panels/helpers/utils.tsx b/public/components/custom_panels/helpers/utils.tsx index 115cbb5ff..c03e33d60 100644 --- a/public/components/custom_panels/helpers/utils.tsx +++ b/public/components/custom_panels/helpers/utils.tsx @@ -355,11 +355,19 @@ const updateCatalogVisualizationQuery = ({ const promQuery = attributesGroupBy.length === 0 ? catalogTableName - : '${aggregation} by(${attributesArrayToString}) (${catalogTableName})'; + : `${aggregation} by(${attributesGroupString}) (${catalogTableName})`; return `source = ${catalogSourceName}.query_range('${promQuery}', ${startEpochTime}, ${endEpochTime}, '14')`; }; +const getAttributesForCatalog = async (pplService, catalogName) => { + const columnSchema = await pplService.fetch({ + query: 'describe ' + catalogName, // + ' | fields COLUMN_NAME, DATA_TYPE', + format: 'jdbc', + }); + return columnSchema.jsonData.map((sch) => sch.COLUMN_NAME).filter((col) => col[0] !== '@'); +}; + // Creates a catalogVisualization for a runtime catalog based PPL query and runs getQueryResponse export const renderCatalogVisualization = async ({ http, @@ -377,6 +385,7 @@ export const renderCatalogVisualization = async ({ setIsError, spanResolution, metricMetaData, + setMetricMetaData, }: { http: CoreStart['http']; pplService: PPLService; @@ -393,6 +402,7 @@ export const renderCatalogVisualization = async ({ setIsError: React.Dispatch>; spanResolution?: string; metricMetaData?: MetricType; + setMetricMetaData?: React.Dispatch>; }) => { setIsLoading(true); setIsError({} as VizContainerError); @@ -405,6 +415,15 @@ export const renderCatalogVisualization = async ({ const defaultAggregation = 'avg'; // pass in attributes to this function // const attributes: string[] = ['instance', 'job']; // pass in attributes to this function + if (metricMetaData) { + if (!metricMetaData.query.availableAttributes) { + const availableAttributes = await getAttributesForCatalog(pplService, catalogSource); + setMetricMetaData!({ + ...metricMetaData, + query: { ...metricMetaData.query, availableAttributes }, + }); + } + } const visualizationQuery = updateCatalogVisualizationQuery({ catalogSourceName, diff --git a/public/components/custom_panels/panel_modules/visualization_container/visualization_container.scss b/public/components/custom_panels/panel_modules/visualization_container/visualization_container.scss index 0130b340f..e3ac33b88 100644 --- a/public/components/custom_panels/panel_modules/visualization_container/visualization_container.scss +++ b/public/components/custom_panels/panel_modules/visualization_container/visualization_container.scss @@ -34,6 +34,12 @@ text-align: center; } +.visualization-div.metricVis { + height: calc(100% - 85px) !important; + +} + + %center-div { top: 50%; left: 50%; diff --git a/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx b/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx index bc4c5afeb..ef231ae10 100644 --- a/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx +++ b/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx @@ -77,7 +77,7 @@ interface Props { catalogVisualization?: boolean; spanParam?: string; metricMetaData?: MetricType; - setMetricMetaData?: (metricMetaData: MetricType) => void; + setMetricMetaData?: React.Dispatch>; contextMenuId: 'visualization' | 'notebook' | 'metrics'; } @@ -295,6 +295,7 @@ export const VisualizationContainer = ({ setIsLoading, setIsError, metricMetaData, + setMetricMetaData, }); else await renderSavedVisualization( @@ -315,9 +316,11 @@ export const VisualizationContainer = ({ ); }; + const metricVisCss = metricMetaData ? 'metricVis' : ''; + const memoisedVisualizationBox = useMemo( () => ( -
+
{isLoading ? ( ) : !_.isEmpty(isError) ? ( @@ -361,9 +364,14 @@ export const VisualizationContainer = ({ setAvailableAttributeKeys(attributeKeys); }, [visualizationData]); - const updateMetricConfig = ({ aggregation }: { aggregation: string }) => { - console.log('updateMetricsConfig', { aggregation }); - setMetricMetaData!({ query: { aggregation } }); + const updateMetricConfig = ({ + aggregation, + attributesGroupBy, + }: { + aggregation: string; + attributesGroupBy: string[]; + }) => { + setMetricMetaData!({ query: { aggregation, attributesGroupBy } }); }; return ( @@ -386,13 +394,6 @@ export const VisualizationContainer = ({ - - - {editMode ? ( +
{memoisedVisualizationBox} diff --git a/public/components/metrics/sidebar/metrics_edit_inline.tsx b/public/components/metrics/sidebar/metrics_edit_inline.tsx index 84c524bab..cd8a4f84f 100644 --- a/public/components/metrics/sidebar/metrics_edit_inline.tsx +++ b/public/components/metrics/sidebar/metrics_edit_inline.tsx @@ -10,6 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiFormLabel, + EuiFormRow, EuiPopover, EuiPopoverTitle, EuiSelect, @@ -35,106 +36,73 @@ export const MetricsEditInline = ({ visualizationData?: any; metricMetaData?: MetricType; updateMetricConfig: ({}: { aggregation?: string; attributesGroupBy?: string[] }) => void; + availableAttributes?: string[]; }) => { const [aggregationIsOpen, setAggregationIsOpen] = useState(false); const [attributesGroupByIsOpen, setAttributesGroupByIsOpen] = useState(false); - const [availableAttributes, setAvailableAttributes] = useState([]); - useObservable( - from(visualizationData?.datarows || []).pipe( - mergeMap((row) => Object.keys(row[0])), - filter((attributeKey) => attributeKey !== '__name__'), - distinct((attributeKey) => attributeKey), - map((attributeKey) => ({ label: attributeKey, value: attributeKey })), - toArray() - ), - setAvailableAttributes, - [visualizationData] - ); + const availableAttributesLabels = + metricMetaData?.query?.availableAttributes?.map((attribute) => ({ + label: attribute, + name: attribute, + })) || []; + const selectedOptionsFrom = (query) => { + return query.attributesGroupBy.map((attribute) => ({ label: attribute, name: attribute })); + }; // useEffect(() => { // console.log({ availableAttributes }); // }, [availableAttributes]); - const onChangeAggregation = (e) => { - updateMetricConfig({ aggregation: e.target.value }); + const onChangeAggregation = (value) => { + updateMetricConfig({ aggregation: value }); setAggregationIsOpen(false); }; - const onChangeAttributesGroupBy = (e) => { - updateMetricConfig({ selectedAttributesGroupBy: e.target.value }); + const onChangeAttributesGroupBy = (selectedAttributes) => { + const attributesGroupBy = selectedAttributes.map(({ label }) => label); + updateMetricConfig({ attributesGroupBy }); + setAttributesGroupByIsOpen(false); }; - useEffect(() => { - console.log({ availableAttributes, metricMetaData, visualizationData }); - }, [availableAttributes, metricMetaData, visualizationData]); - const renderAggregationEditor = () => ( -
- Aggregation - -
+ + + + + + + ); const renderAttributesGroupByEditor = () => ( -
- Group By Attributes - -
+ + + + + + + ); return (
- - setAggregationIsOpen(true)} - /> - } - isOpen={aggregationIsOpen} - closePopover={() => setAggregationIsOpen(false)} - panelPaddingSize="s" - anchorPosition="downLeft" - > - {renderAggregationEditor()} - - - - setAttributesGroupByIsOpen(true)} - /> - } - isOpen={attributesGroupByIsOpen} - closePopover={() => setAttributesGroupByIsOpen(false)} - panelPaddingSize="s" - anchorPosition="downLeft" - > - {renderAttributesGroupByEditor()} - - + {renderAggregationEditor()} + {renderAttributesGroupByEditor()}
);