Skip to content

Commit

Permalink
Metrics Explorer updated with PromQL query for Prometheus Metrics and…
Browse files Browse the repository at this point in the history
… updated Export Panel

Signed-off-by: Peter Fitzgibbons <peter.fitzgibbons@gmail.com>
  • Loading branch information
pjfitzgibbons committed Dec 7, 2023
1 parent f252fb1 commit 65eb3aa
Show file tree
Hide file tree
Showing 66 changed files with 2,066 additions and 1,646 deletions.
15 changes: 7 additions & 8 deletions common/constants/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

export const METRIC_EXPLORER_BASE_PATH = 'observability-metrics#/';

// requests constants
export const VISUALIZATION = 'viz';
export const SAVED_VISUALIZATION = 'savedVisualization';
Expand All @@ -24,13 +26,10 @@ export const resolutionOptions = [
{ value: 'y', text: 'years' },
];

export const DEFAULT_METRIC_HEIGHT = 2;
export const DEFAULT_METRIC_WIDTH = 12;

export const AGGREGATION_OPTIONS = [
{ label: 'avg' },
{ label: 'sum' },
{ label: 'count' },
{ label: 'min' },
{ label: 'max' },
{ value: 'avg', text: 'avg()' },
{ value: 'sum', text: 'sum()' },
{ value: 'count', text: 'count()' },
{ value: 'min', text: 'min()' },
{ value: 'max', text: 'max()' },
];
6 changes: 6 additions & 0 deletions common/constants/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ export const PPL_PATTERNS_DOCUMENTATION_URL =
export const UI_DATE_FORMAT = 'MM/DD/YYYY hh:mm A';
export const PPL_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSSSSS';
export const SPAN_REGEX = /span/;

export const PROMQL_METRIC_SUBTYPE = 'promqlmetric';
export const PPL_METRIC_SUBTYPE = 'metric';

export const PPL_SPAN_REGEX = /by\s*span/i;
export const PPL_STATS_REGEX = /\|\s*stats/i;
export const PPL_INDEX_INSERT_POINT_REGEX = /(search source|source|index)\s*=\s*([^|\s]+)(.*)/i;
Expand Down Expand Up @@ -190,6 +194,7 @@ export const LIVE_OPTIONS = [
];

export const LIVE_END_TIME = 'now';

export interface DefaultChartStylesProps {
DefaultModeLine: string;
Interpolation: string;
Expand Down Expand Up @@ -243,6 +248,7 @@ export const VISUALIZATION_ERROR = {
NO_DATA: 'No data found.',
INVALID_DATA: 'Invalid visualization data',
NO_SERIES: 'Add a field to start',
NO_METRIC: 'Invalid Metric MetaData',
};

export const S3_DATASOURCE_TYPE = 'S3_DATASOURCE';
Expand Down
2 changes: 1 addition & 1 deletion common/types/custom_panels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface SavedVisualizationType {
selected_date_range: { start: string; end: string; text: string };
timeField: string;
application_id?: string;
user_configs: any;
userConfigs: any;
}

export interface PPLResponse {
Expand Down
26 changes: 14 additions & 12 deletions common/types/explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ import Plotly from 'plotly.js-dist';
import { QueryManager } from 'common/query_manager';
import { VIS_CHART_TYPES } from '../../common/constants/shared';
import {
RAW_QUERY,
SELECTED_FIELDS,
UNSELECTED_FIELDS,
AGGREGATIONS,
AVAILABLE_FIELDS,
QUERIED_FIELDS,
INDEX,
BREAKDOWNS,
CUSTOM_LABEL,
FINAL_QUERY,
SELECTED_TIMESTAMP,
SELECTED_DATE_RANGE,
GROUPBY,
AGGREGATIONS,
CUSTOM_LABEL,
BREAKDOWNS,
INDEX,
QUERIED_FIELDS,
RAW_QUERY,
SELECTED_DATE_RANGE,
SELECTED_FIELDS,
SELECTED_TIMESTAMP,
UNSELECTED_FIELDS,
} from '../constants/explorer';
import {
CoreStart,
CoreSetup,
CoreStart,
HttpSetup,
HttpStart,
NotificationsStart,
Expand All @@ -39,6 +39,7 @@ import {
} from '../../../../src/core/public/saved_objects';
import { ChromeBreadcrumb } from '../../../../src/core/public/chrome';
import { DataSourceType } from '../../../../src/plugins/data/public';
import { PROMQL_METRIC_SUBTYPE } from '../constants/shared';

export interface IQueryTab {
id: string;
Expand Down Expand Up @@ -173,7 +174,7 @@ export interface SavedVisualization extends SavedObjectAttributes {
selected_fields: { text: string; tokens: [] };
selected_timestamp: IField;
type: string;
sub_type?: 'metric' | 'visualization'; // exists if sub type is metric
subType?: 'metric' | 'visualization' | typeof PROMQL_METRIC_SUBTYPE; // exists if sub type is metric
user_configs?: string;
units_of_measure?: string;
application_id?: string;
Expand Down Expand Up @@ -346,6 +347,7 @@ export interface DataConfigPanelProps {
visualizations: IVisualizationContainerProps;
queryManager?: QueryManager;
}

export interface GetTooltipHoverInfoType {
tooltipMode: string;
tooltipText: string;
Expand Down
14 changes: 7 additions & 7 deletions common/types/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@

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';
query: {
type: 'savedCustomMetric' | 'prometheusMetric';
aggregation: string;
attributesGroupBy: string[];
catalog: string;
availableAttributes?: string[];
};
}
4 changes: 3 additions & 1 deletion public/components/application_analytics/helpers/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ export const calculateAvailability = async (
const visData = await fetchVisualizationById(http, visualizationId, (value: string) =>
console.error(value)
);
const userConfigs = visData.user_configs ? JSON.parse(visData.user_configs) : {};
const userConfigs = visData.userConfigs
? JSON.parse(visData.user_configs || visData.userConfigs)
: {};
// If there are levels, we get the current value
if (userConfigs.availabilityConfig?.hasOwnProperty('level')) {
// For every saved visualization with availability levels we push it to visWithAvailability
Expand Down
54 changes: 46 additions & 8 deletions public/components/common/query_utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import dateMath from '@elastic/datemath';
import { Moment } from 'moment-timezone';
import { isEmpty } from 'lodash';
import { SearchMetaData } from 'public/components/event_analytics/redux/slices/search_meta_data_slice';
import { SearchMetaData } from '../../event_analytics/redux/slices/search_meta_data_slice';
import {
PPL_DEFAULT_PATTERN_REGEX_FILETER,
SELECTED_DATE_RANGE,
Expand All @@ -20,6 +20,7 @@ import {
PPL_NEWLINE_REGEX,
} from '../../../../common/constants/shared';
import { IExplorerFields, IQuery } from '../../../../common/types/explorer';
import { updateCatalogVisualizationQuery } from '../../custom_panels/helpers/utils';

/*
* "Query Utils" This file contains different reused functions in operational panels
Expand All @@ -35,6 +36,32 @@ const escapeQuotes = (literal: string) => {
return literal.replaceAll("'", "''");
};

export const findMinInterval = (start: string = '', end: string = '') => {
const momentStart = dateMath.parse(start)!;
const momentEnd = dateMath.parse(end, { roundUp: true })!;
const diffSeconds = momentEnd.unix() - momentStart.unix();
let minInterval = 'y';

// less than 1 second
if (diffSeconds <= 1) minInterval = 'ms';
// less than 2 minutes
else if (diffSeconds <= 60 * 2) minInterval = 's';
// less than 2 hours
else if (diffSeconds <= 3600 * 2) minInterval = 'm';
// less than 2 days
else if (diffSeconds <= 86400 * 2) minInterval = 'h';
// less than 1 month
else if (diffSeconds <= 86400 * 31) minInterval = 'd';
// less than 3 months
else if (diffSeconds <= 86400 * 93) minInterval = 'w';
// less than 2 year
else if (diffSeconds <= 86400 * 366) minInterval = 'w';

console.log('findMinInterval', { momentStart, momentEnd, diffSeconds, minInterval });

return minInterval;
};

export const convertDateTime = (
datetime: string,
isStart = true,
Expand Down Expand Up @@ -128,13 +155,6 @@ export const updatePromQLQueryFilters = (
const { connection, metric, aggregation, attributesGroupBy } = parsePromQLIntoKeywords(
promQLQuery
);
console.log('updatePromQLQueryFilters', {
connection,
metric,
aggregation,
attributesGroupBy,
promQLQuery,
});
const promQLPart = buildPromQLFromMetricQuery({
metric,
attributesGroupBy: attributesGroupBy.split(','),
Expand All @@ -157,6 +177,24 @@ export const getIndexPatternFromRawQuery = (query: string): string => {
return getPromQLIndex(query) || getPPLIndex(query);
};

export const preprocessMetricQuery = ({ metaData, startTime, endTime }) => {
// convert to moment
const start = convertDateTime(startTime, true);
const end = convertDateTime(endTime, false);

const resolution = findMinInterval(start, end);

const visualizationQuery = updateCatalogVisualizationQuery({
...metaData.queryMetaData,
start,
end,
span: '1',
resolution,
});

return visualizationQuery;
};

// insert time filter command and additional commands based on raw query
export const preprocessQuery = ({
rawQuery,
Expand Down
10 changes: 7 additions & 3 deletions public/components/common/search/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,13 @@ export const Search = (props: any) => {
}
curVisId={curVisId}
setSubType={setSubType}
isSaveAsMetricEnabled={
isEqual(curVisId, 'line') && tempQuery.match(PPL_SPAN_REGEX) !== null
}
isSaveAsMetricEnabled={() => {
return (
isEqual(curVisId, 'line') &&
tempQuery &&
tempQuery.match(PPL_SPAN_REGEX) !== null
);
}}
/>
<EuiPopoverFooter>
<EuiFlexGroup justifyContent="flexEnd">
Expand Down
14 changes: 10 additions & 4 deletions public/components/custom_panels/custom_panel_view_so.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import { addVisualizationPanel } from './helpers/add_visualization_helper';
import { AddVisualizationPopover } from './helpers/add_visualization_popover';
import { getCustomModal } from './helpers/modal_containers';
import {
convertDateTime,
isDateValid,
isNameValid,
isPPLFilterValid,
Expand All @@ -66,7 +65,8 @@ import {
import { useToast } from '../common/toast';
import PPLService from '../../services/requests/ppl';
import DSLService from '../../services/requests/dsl';

import { convertDateTime } from '../common/query_utils';

/*
* "CustomPanelsView" module used to render an Observability Dashboard
*
Expand Down Expand Up @@ -181,7 +181,9 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => {
timeProps.end,
recentlyUsedRanges
);
dispatch(updatePanel({ ...panel, timeRange: { from: timeProps.start, to: timeProps.end } }, '', ''));
dispatch(
updatePanel({ ...panel, timeRange: { from: timeProps.start, to: timeProps.end } }, '', '')
);

setRecentlyUsedRanges(updatedRanges.slice(0, 9));
onRefreshFilters(timeProps.start, timeProps.end);
Expand Down Expand Up @@ -354,7 +356,11 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => {
};

const cloneVisualization = (visualzationTitle: string, savedVisualizationId: string) => {
addVisualizationToCurrentPanel({ savedVisualizationId, successMsg: `Visualization ${visualzationTitle} successfully added!`, failureMsg: `Error in adding ${visualzationTitle} visualization to the panel` });
addVisualizationToCurrentPanel({
savedVisualizationId,
successMsg: `Visualization ${visualzationTitle} successfully added!`,
failureMsg: `Error in adding ${visualzationTitle} visualization to the panel`,
});
};

const cancelButton = (
Expand Down
Loading

0 comments on commit 65eb3aa

Please sign in to comment.