Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge feature/metrics branch to 2.4 #1234

Merged
merged 11 commits into from
Nov 3, 2022
12 changes: 11 additions & 1 deletion dashboards-observability/common/constants/explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const TAB_CHART_ID_TXT_PFX = 'main-content-vis-';
export const TAB_EVENT_ID = 'main-content-events';
export const TAB_CHART_ID = 'main-content-vis';
export const HAS_SAVED_TIMESTAMP = 'hasSavedTimestamp';
export const FILTER_OPTIONS = ['Visualization', 'Query'];
export const FILTER_OPTIONS = ['Visualization', 'Query', 'Metric'];
export const SAVED_QUERY = 'savedQuery';
export const SAVED_VISUALIZATION = 'savedVisualization';
export const SAVED_OBJECT_ID = 'savedObjectId';
Expand Down Expand Up @@ -289,3 +289,13 @@ export const DATA_CONFIG_HINTS_INFO = {
[BREAKDOWNS]:
"Defines how each series is broken down. Breakdowns are 'by' clauses that subdivide the existing series.",
};

// Metrics constants
export const UNITS_OF_MEASURE = [
'seconds (s)',
'hours (h)',
'celsius (C)',
'farenheit (F)',
'meters (m)',
'kilometers (k)',
]
26 changes: 26 additions & 0 deletions dashboards-observability/common/constants/metrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

// requests constants
export const VISUALIZATION = 'viz';
export const SAVED_VISUALIZATION = 'savedVisualization';
export const PPL_PROMETHEUS_CATALOG_REQUEST =
'show catalogs | where CONNECTOR_TYPE="PROMETHEUS" | fields CATALOG_NAME';

// redux
export const REDUX_SLICE_METRICS = 'metrics';

export const resolutionOptions = [
{ value: 's', text: 'seconds' },
{ value: 'm', text: 'minutes' },
{ value: 'h', text: 'hours' },
{ value: 'd', text: 'days' },
{ value: 'M', text: 'Months' },
{ value: 'q', text: 'quarters' },
{ value: 'y', text: 'years' },
];

export const DEFAULT_METRIC_HEIGHT = 2;
export const DEFAULT_METRIC_WIDTH = 12;
22 changes: 22 additions & 0 deletions dashboards-observability/common/types/metrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { VisualizationType } from './custom_panels';

export interface MetricData {
metricId: string;
metricType: 'savedCustomMetric' | 'prometheusMetric';
metricName: string;
}

export interface MetricType extends VisualizationType {
id: string;
savedVisualizationId: string;
x: number;
y: number;
w: number;
h: number;
metricType: 'savedCustomMetric' | 'prometheusMetric';
}
19 changes: 19 additions & 0 deletions dashboards-observability/public/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Home as CustomPanelsHome } from './custom_panels/home';
import { EventAnalytics } from './event_analytics';
import { Main as NotebooksHome } from './notebooks/components/main';
import { Home as TraceAnalyticsHome } from './trace_analytics/home';
import { Home as MetricsHome } from './metrics/index';

interface ObservabilityAppDeps {
CoreStartProp: CoreStart;
Expand Down Expand Up @@ -59,6 +60,24 @@ export const App = ({
<I18nProvider>
<>
<Switch>
<Route
path="/metrics"
render={(props) => {
chrome.setBreadcrumbs([
parentBreadcrumb,
{ text: 'Metrics', href: '#/metrics/' },
]);
return (
<MetricsHome
http={http}
chrome={chrome}
parentBreadcrumb={parentBreadcrumb}
renderProps={props}
pplService={pplService}
/>
);
}}
/>
<Route
path={'/application_analytics'}
render={(props) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('Search bar', () => {
const popoverItems = jest.fn();
const isLiveTailOn = jest.fn();
const countDistribution = jest.fn();
const setMetricLabel = jest.fn();
const utils = render(
<Search
key="search-component"
Expand Down Expand Up @@ -61,6 +62,11 @@ describe('Search bar', () => {
popoverItems={popoverItems}
isLiveTailOn={isLiveTailOn}
countDistribution={countDistribution}
curVisId={'line'}
spanValue={false}
setSubType={'metric'}
setMetricMeasure={'hours (h)'}
setMetricLabel={setMetricLabel}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ export const Search = (props: any) => {
setIsLiveTailPopoverOpen,
liveTailName,
searchError = null,
curVisId,
spanValue,
setSubType,
setMetricMeasure,
setMetricLabel,
} = props;

const appLogEvents = tabId.match(APP_ANALYTICS_TAB_ID_REGEX);
Expand Down Expand Up @@ -214,7 +219,13 @@ export const Search = (props: any) => {
showOptionList={
showSavePanelOptionsList &&
searchBarConfigs[selectedSubTabId]?.showSavePanelOptionsList

}
curVisId={curVisId}
spanValue={spanValue}
setSubType={setSubType}
setMetricMeasure={setMetricMeasure}
setMetricLabel={setMetricLabel}
/>
<EuiPopoverFooter>
<EuiFlexGroup justifyContent="flexEnd">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ export function ObservabilitySideBar(props: { children: React.ReactNode }) {
id: 5,
href: '#/notebooks',
},
{
name: 'Metrics',
id: 6,
href: '#/metrics',
},
],
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import dateMath from '@elastic/datemath';
import { ShortDate } from '@elastic/eui';
import { DurationRange } from '@elastic/eui/src/components/date_picker/types';
import _, { isEmpty } from 'lodash';
import _ from 'lodash';
import { Moment } from 'moment-timezone';
import React from 'react';
import { Layout } from 'react-grid-layout';
Expand Down Expand Up @@ -88,7 +88,8 @@ const queryAccumulator = (
timestampField: string,
startTime: string,
endTime: string,
panelFilterQuery: string
panelFilterQuery: string,
spanParam: string | undefined
) => {
const indexMatchArray = originalQuery.match(PPL_INDEX_REGEX);
if (indexMatchArray == null) {
Expand All @@ -100,7 +101,15 @@ const queryAccumulator = (
startTime
)}' and ${timestampField} <= '${convertDateTime(endTime, false)}'`;
const pplFilterQuery = panelFilterQuery === '' ? '' : ` | ${panelFilterQuery}`;
return indexPartOfQuery + timeQueryFilter + pplFilterQuery + filterPartOfQuery;
const finalQuery = indexPartOfQuery + timeQueryFilter + pplFilterQuery + filterPartOfQuery;
if (spanParam === undefined) {
return finalQuery;
} else {
return finalQuery.replace(
new RegExp(`span\\(${timestampField},(.*?)\\)`),
`span(${timestampField},${spanParam})`
);
}
};

// PPL Service requestor
Expand Down Expand Up @@ -154,6 +163,7 @@ export const getQueryResponse = (
type: string,
startTime: string,
endTime: string,
spanParam: string | undefined,
setVisualizationData: React.Dispatch<React.SetStateAction<any[]>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>,
Expand All @@ -165,7 +175,14 @@ export const getQueryResponse = (

let finalQuery = '';
try {
finalQuery = queryAccumulator(query, timestampField, startTime, endTime, filterQuery);
finalQuery = queryAccumulator(
query,
timestampField,
startTime,
endTime,
filterQuery,
spanParam
);
} catch (error) {
const errorMessage = 'Issue in building final query';
setIsError(errorMessage);
Expand All @@ -185,6 +202,7 @@ export const renderSavedVisualization = async (
startTime: string,
endTime: string,
filterQuery: string,
spanParam: string | undefined,
setVisualizationTitle: React.Dispatch<React.SetStateAction<string>>,
setVisualizationType: React.Dispatch<React.SetStateAction<string>>,
setVisualizationData: React.Dispatch<React.SetStateAction<Plotly.Data[]>>,
Expand Down Expand Up @@ -219,6 +237,7 @@ export const renderSavedVisualization = async (
visualization.type,
startTime,
endTime,
spanParam,
setVisualizationData,
setIsLoading,
setIsError,
Expand All @@ -227,6 +246,83 @@ export const renderSavedVisualization = async (
);
};

const createCatalogVisualizationMetaData = (
catalogSource: string,
visualizationQuery: string,
visualizationType: string,
visualizationTimeField: string
) => {
return {
name: catalogSource,
description: '',
query: visualizationQuery,
type: visualizationType,
selected_date_range: {
start: 'now/y',
end: 'now',
text: '',
},
selected_timestamp: {
name: visualizationTimeField,
type: 'timestamp',
},
selected_fields: {
text: '',
tokens: [],
},
};
};

//Creates a catalogVisualization for a runtime catalog based PPL query and runs getQueryResponse
export const renderCatalogVisualization = async (
http: CoreStart['http'],
pplService: PPLService,
catalogSource: string,
startTime: string,
endTime: string,
filterQuery: string,
spanParam: string | undefined,
setVisualizationTitle: React.Dispatch<React.SetStateAction<string>>,
setVisualizationType: React.Dispatch<React.SetStateAction<string>>,
setVisualizationData: React.Dispatch<React.SetStateAction<Plotly.Data[]>>,
setVisualizationMetaData: React.Dispatch<React.SetStateAction<undefined>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>,
spanResolution?: string
) => {
setIsLoading(true);
setIsError('');

const visualizationType = 'line';
const visualizationTimeField = '@timestamp';
const visualizationQuery = `source = ${catalogSource} | stats avg(@value) by span(${visualizationTimeField},1h)`;

const visualizationMetaData = createCatalogVisualizationMetaData(
catalogSource,
visualizationQuery,
visualizationType,
visualizationTimeField
);
setVisualizationTitle(catalogSource);
setVisualizationType(visualizationType);

setVisualizationMetaData(visualizationMetaData);

getQueryResponse(
pplService,
visualizationQuery,
visualizationType,
startTime,
endTime,
spanParam,
setVisualizationData,
setIsLoading,
setIsError,
filterQuery,
visualizationTimeField
);
};

// Function to store recently used time filters and set start and end time.
export const onTimeChange = (
start: ShortDate,
Expand Down Expand Up @@ -289,7 +385,7 @@ export const isPPLFilterValid = (

// Renders visualization in the vizualization container component
export const displayVisualization = (metaData: any, data: any, type: string) => {
if (metaData === undefined || isEmpty(metaData)) {
if (metaData === undefined || _.isEmpty(metaData)) {
return <></>;
}
return (
Expand Down
Loading