Chore: Refactor some of the prometheus data source types (#107031)
* refactor the types * more refactoring * fix import
This commit is contained in:
@@ -4,9 +4,10 @@ import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { BrowserLabel as PromLabel, Input, Label, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { METRIC_LABEL } from '../../constants';
|
||||
|
||||
import { useMetricsBrowser } from './MetricsBrowserContext';
|
||||
import { getStylesLabelSelector } from './styles';
|
||||
import { METRIC_LABEL } from './types';
|
||||
|
||||
export function LabelSelector() {
|
||||
const styles = useStyles2(getStylesLabelSelector);
|
||||
|
||||
@@ -5,9 +5,10 @@ import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { BrowserLabel as PromLabel, Input, Label, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { LIST_ITEM_SIZE } from '../../constants';
|
||||
|
||||
import { useMetricsBrowser } from './MetricsBrowserContext';
|
||||
import { getStylesMetricSelector } from './styles';
|
||||
import { LIST_ITEM_SIZE } from './types';
|
||||
|
||||
export function MetricSelector() {
|
||||
const styles = useStyles2(getStylesMetricSelector);
|
||||
|
||||
+1
-1
@@ -4,11 +4,11 @@ import { ReactNode } from 'react';
|
||||
|
||||
import { TimeRange } from '@grafana/data';
|
||||
|
||||
import { LAST_USED_LABELS_KEY, METRIC_LABEL } from '../../constants';
|
||||
import { PrometheusLanguageProviderInterface } from '../../language_provider';
|
||||
import { getMockTimeRange } from '../../test/__mocks__/datasource';
|
||||
|
||||
import { MetricsBrowserProvider, useMetricsBrowser } from './MetricsBrowserContext';
|
||||
import { LAST_USED_LABELS_KEY, METRIC_LABEL } from './types';
|
||||
|
||||
const setupLocalStorageMock = () => {
|
||||
let store: Record<string, string> = {};
|
||||
|
||||
+5
-1
@@ -5,9 +5,13 @@ import { TimeRange } from '@grafana/data';
|
||||
import { PrometheusLanguageProviderInterface } from '../../language_provider';
|
||||
|
||||
import { buildSelector } from './selectorBuilder';
|
||||
import { Metric } from './types';
|
||||
import { useMetricsLabelsValues } from './useMetricsLabelsValues';
|
||||
|
||||
export interface Metric {
|
||||
name: string;
|
||||
details?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context for the Metrics Browser component
|
||||
* Provides state and handlers for browsing and selecting Prometheus metrics and labels
|
||||
|
||||
@@ -5,9 +5,10 @@ import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { Button, Label, Stack, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { EMPTY_SELECTOR } from '../../constants';
|
||||
|
||||
import { useMetricsBrowser } from './MetricsBrowserContext';
|
||||
import { getStylesSelectorActions } from './styles';
|
||||
import { EMPTY_SELECTOR } from './types';
|
||||
|
||||
export function SelectorActions() {
|
||||
const styles = useStyles2(getStylesSelectorActions);
|
||||
|
||||
@@ -5,9 +5,10 @@ import { selectors } from '@grafana/e2e-selectors';
|
||||
import { t, Trans } from '@grafana/i18n';
|
||||
import { BrowserLabel as PromLabel, Input, Label, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { LIST_ITEM_SIZE } from '../../constants';
|
||||
|
||||
import { useMetricsBrowser } from './MetricsBrowserContext';
|
||||
import { getStylesValueSelector } from './styles';
|
||||
import { LIST_ITEM_SIZE } from './types';
|
||||
|
||||
export function ValueSelector() {
|
||||
const styles = useStyles2(getStylesValueSelector);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
export interface Metric {
|
||||
name: string;
|
||||
details?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SERIES_LIMIT = '40000';
|
||||
export const REMOVE_SERIES_LIMIT = 'none';
|
||||
export const EMPTY_SELECTOR = '{}';
|
||||
export const METRIC_LABEL = '__name__';
|
||||
export const LIST_ITEM_SIZE = 25;
|
||||
export const LAST_USED_LABELS_KEY = 'grafana.datasources.prometheus.browser.labels';
|
||||
+1
-1
@@ -2,11 +2,11 @@ import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
|
||||
import { TimeRange } from '@grafana/data';
|
||||
|
||||
import { DEFAULT_SERIES_LIMIT, EMPTY_SELECTOR, LAST_USED_LABELS_KEY, METRIC_LABEL } from '../../constants';
|
||||
import { PrometheusLanguageProviderInterface } from '../../language_provider';
|
||||
import { getMockTimeRange } from '../../test/__mocks__/datasource';
|
||||
|
||||
import * as selectorBuilderModule from './selectorBuilder';
|
||||
import { DEFAULT_SERIES_LIMIT, EMPTY_SELECTOR, LAST_USED_LABELS_KEY, METRIC_LABEL } from './types';
|
||||
import { useMetricsLabelsValues } from './useMetricsLabelsValues';
|
||||
|
||||
// Test utilities to reduce boilerplate
|
||||
|
||||
+2
-1
@@ -3,10 +3,11 @@ import { useDebounce } from 'react-use';
|
||||
|
||||
import { TimeRange } from '@grafana/data';
|
||||
|
||||
import { DEFAULT_SERIES_LIMIT, EMPTY_SELECTOR, LAST_USED_LABELS_KEY, METRIC_LABEL } from '../../constants';
|
||||
import { PrometheusLanguageProviderInterface } from '../../language_provider';
|
||||
|
||||
import { Metric } from './MetricsBrowserContext';
|
||||
import { buildSelector } from './selectorBuilder';
|
||||
import { DEFAULT_SERIES_LIMIT, EMPTY_SELECTOR, LAST_USED_LABELS_KEY, Metric, METRIC_LABEL } from './types';
|
||||
|
||||
export const useMetricsLabelsValues = (timeRange: TimeRange, languageProvider: PrometheusLanguageProviderInterface) => {
|
||||
const timeRangeRef = useRef<TimeRange>(timeRange);
|
||||
|
||||
@@ -6,9 +6,10 @@ import { SelectableValue } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import { countError } from '../constants';
|
||||
import { createDefaultConfigOptions } from '../test/__mocks__/datasource';
|
||||
|
||||
import { countError, getValueFromEventItem, PromSettings } from './PromSettings';
|
||||
import { getValueFromEventItem, PromSettings } from './PromSettings';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.replaceProperty(config, 'featureToggles', {
|
||||
|
||||
@@ -15,7 +15,9 @@ import { config } from '@grafana/runtime';
|
||||
import { InlineField, Input, Select, Switch, TextLink, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import {
|
||||
countError,
|
||||
DURATION_REGEX,
|
||||
durationError,
|
||||
MULTIPLE_DURATION_REGEX,
|
||||
NON_NEGATIVE_INTEGER_REGEX,
|
||||
PROM_CONFIG_LABEL_WIDTH,
|
||||
@@ -29,6 +31,8 @@ import { ExemplarsSettings } from './ExemplarsSettings';
|
||||
import { PromFlavorVersions } from './PromFlavorVersions';
|
||||
import { docsTip, overhaulStyles, validateInput } from './shared/utils';
|
||||
|
||||
type Props = Pick<DataSourcePluginOptionsEditorProps<PromOptions>, 'options' | 'onOptionsChange'>;
|
||||
|
||||
const httpOptions = [
|
||||
{ value: 'POST', label: 'POST' },
|
||||
{ value: 'GET', label: 'GET' },
|
||||
@@ -48,6 +52,16 @@ const cacheValueOptions = [
|
||||
|
||||
type PrometheusSelectItemsType = Array<{ value: PromApplication; label: PromApplication }>;
|
||||
|
||||
type ValidDuration = {
|
||||
timeInterval: string;
|
||||
queryTimeout: string;
|
||||
incrementalQueryOverlapWindow: string;
|
||||
};
|
||||
|
||||
type ValidCount = {
|
||||
codeModeMetricNamesSuggestionLimit: string;
|
||||
};
|
||||
|
||||
const prometheusFlavorSelectItems: PrometheusSelectItemsType = [
|
||||
{ value: PromApplication.Prometheus, label: PromApplication.Prometheus },
|
||||
{ value: PromApplication.Cortex, label: PromApplication.Cortex },
|
||||
@@ -55,11 +69,6 @@ const prometheusFlavorSelectItems: PrometheusSelectItemsType = [
|
||||
{ value: PromApplication.Thanos, label: PromApplication.Thanos },
|
||||
];
|
||||
|
||||
type Props = Pick<DataSourcePluginOptionsEditorProps<PromOptions>, 'options' | 'onOptionsChange'>;
|
||||
|
||||
const durationError = 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s';
|
||||
export const countError = 'Value is not valid, you can use non-negative integers, including scientific notation';
|
||||
|
||||
const getOptionsWithDefaults = (options: DataSourceSettings<PromOptions>) => {
|
||||
if (options.jsonData.httpMethod) {
|
||||
return options;
|
||||
@@ -71,28 +80,17 @@ const getOptionsWithDefaults = (options: DataSourceSettings<PromOptions>) => {
|
||||
};
|
||||
|
||||
export const PromSettings = (props: Props) => {
|
||||
const { onOptionsChange } = props;
|
||||
const optionsWithDefaults = getOptionsWithDefaults(props.options);
|
||||
|
||||
const theme = useTheme2();
|
||||
const styles = overhaulStyles(theme);
|
||||
const { onOptionsChange } = props;
|
||||
|
||||
type ValidDuration = {
|
||||
timeInterval: string;
|
||||
queryTimeout: string;
|
||||
incrementalQueryOverlapWindow: string;
|
||||
};
|
||||
|
||||
const optionsWithDefaults = getOptionsWithDefaults(props.options);
|
||||
const [validDuration, updateValidDuration] = useState<ValidDuration>({
|
||||
timeInterval: '',
|
||||
queryTimeout: '',
|
||||
incrementalQueryOverlapWindow: '',
|
||||
});
|
||||
|
||||
type ValidCount = {
|
||||
codeModeMetricNamesSuggestionLimit: string;
|
||||
};
|
||||
|
||||
const [validCount, updateValidCount] = useState<ValidCount>({
|
||||
codeModeMetricNamesSuggestionLimit: '',
|
||||
});
|
||||
|
||||
@@ -5,6 +5,9 @@ export const PROMETHEUS_QUERY_BUILDER_MAX_RESULTS = 1000;
|
||||
|
||||
export const PROM_CONFIG_LABEL_WIDTH = 30;
|
||||
|
||||
export const LIST_ITEM_SIZE = 25;
|
||||
export const LAST_USED_LABELS_KEY = 'grafana.datasources.prometheus.browser.labels';
|
||||
|
||||
// single duration input
|
||||
export const DURATION_REGEX = /^$|^\d+(ms|[Mwdhmsy])$/;
|
||||
|
||||
@@ -13,5 +16,16 @@ export const MULTIPLE_DURATION_REGEX = /(\d+)(.+)/;
|
||||
|
||||
export const NON_NEGATIVE_INTEGER_REGEX = /^(0|[1-9]\d*)(\.\d+)?(e\+?\d+)?$/; // non-negative integers, including scientific notation
|
||||
|
||||
export const EMPTY_SELECTOR = '{}';
|
||||
export const DEFAULT_SERIES_LIMIT = '40000';
|
||||
export const MATCH_ALL_LABELS_STR = '__name__!=""';
|
||||
export const MATCH_ALL_LABELS = '{__name__!=""}';
|
||||
export const METRIC_LABEL = '__name__';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const REMOVE_SERIES_LIMIT = 'none';
|
||||
|
||||
export const durationError = 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s';
|
||||
export const countError = 'Value is not valid, you can use non-negative integers, including scientific notation';
|
||||
|
||||
@@ -3,14 +3,13 @@ import { AbstractLabelOperator, dateTime, TimeRange } from '@grafana/data';
|
||||
|
||||
jest.mock('./language_utils', () => ({
|
||||
...jest.requireActual('./language_utils'),
|
||||
processHistogramMetrics: (metrics: string[]) => metrics,
|
||||
getPrometheusTime: jest.requireActual('./language_utils').getPrometheusTime,
|
||||
getRangeSnapInterval: jest.requireActual('./language_utils').getRangeSnapInterval,
|
||||
}));
|
||||
|
||||
import { getCacheDurationInMinutes } from './caching';
|
||||
import { DEFAULT_SERIES_LIMIT } from './components/metrics-browser/types';
|
||||
import { Label } from './components/monaco-query-field/monaco-completion-provider/situation';
|
||||
import { DEFAULT_SERIES_LIMIT } from './constants';
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import {
|
||||
exportToAbstractQuery,
|
||||
@@ -308,7 +307,7 @@ describe('Prometheus Language Provider', () => {
|
||||
const fetchSeriesLabels = languageProvider.fetchSeriesLabels;
|
||||
const requestSpy = jest.spyOn(languageProvider, 'request');
|
||||
|
||||
fetchSeriesLabels(getMockTimeRange(), '$metric');
|
||||
fetchSeriesLabels(getMockTimeRange(), '$metric', undefined, DEFAULT_SERIES_LIMIT);
|
||||
|
||||
verifyRequestParams(requestSpy, '/api/v1/series', {
|
||||
end: toPrometheusTimeString,
|
||||
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
import { BackendSrvRequest } from '@grafana/runtime';
|
||||
|
||||
import { buildCacheHeaders, getDaysToCacheMetadata, getDefaultCacheHeaders } from './caching';
|
||||
import { DEFAULT_SERIES_LIMIT, REMOVE_SERIES_LIMIT } from './components/metrics-browser/types';
|
||||
import { Label } from './components/monaco-query-field/monaco-completion-provider/situation';
|
||||
import { DEFAULT_SERIES_LIMIT, MATCH_ALL_LABELS_STR, EMPTY_SELECTOR, REMOVE_SERIES_LIMIT } from './constants';
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import {
|
||||
extractLabelMatchers,
|
||||
@@ -30,11 +30,10 @@ import {
|
||||
import PromqlSyntax from './promql';
|
||||
import { buildVisualQueryFromString } from './querybuilder/parsing';
|
||||
import { LabelsApiClient, ResourceApiClient, SeriesApiClient } from './resource_clients';
|
||||
import { MATCH_ALL_LABELS_STR, PromMetricsMetadata, PromQuery } from './types';
|
||||
import { PromMetricsMetadata, PromQuery } from './types';
|
||||
import { escapeForUtf8Support, isValidLegacyName } from './utf8_support';
|
||||
|
||||
const DEFAULT_KEYS = ['job', 'instance'];
|
||||
const EMPTY_SELECTOR = '{}';
|
||||
|
||||
/**
|
||||
* Prometheus API endpoints for fetching resources
|
||||
|
||||
@@ -3,6 +3,7 @@ import { map as _map } from 'lodash';
|
||||
|
||||
import { MetricFindValue, TimeRange } from '@grafana/data';
|
||||
|
||||
import { METRIC_LABEL } from './constants';
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import { getPrometheusTime } from './language_utils';
|
||||
import {
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
PrometheusQueryResultRegex,
|
||||
} from './migrations/variableMigration';
|
||||
import { getOriginalMetricName } from './result_transformer';
|
||||
import { METRIC_LABEL } from './types';
|
||||
|
||||
export class PrometheusMetricFindQuery {
|
||||
constructor(
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n';
|
||||
import { EditorField, EditorFieldGroup, InputGroup } from '@grafana/plugin-ui';
|
||||
import { Button, InlineField, InlineFieldRow, Combobox, ComboboxOption } from '@grafana/ui';
|
||||
|
||||
import { METRIC_LABEL } from '../../components/metrics-browser/types';
|
||||
import { METRIC_LABEL } from '../../constants';
|
||||
import { PrometheusDatasource } from '../../datasource';
|
||||
import { regexifyLabelValuesQueryString } from '../parsingUtils';
|
||||
import { QueryBuilderLabelFilter } from '../shared/types';
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import {
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { getDebounceTimeInMilliseconds } from '../../../caching';
|
||||
import { METRIC_LABEL } from '../../../components/metrics-browser/types';
|
||||
import { METRIC_LABEL } from '../../../constants';
|
||||
import { regexifyLabelValuesQueryString } from '../../parsingUtils';
|
||||
import { formatPrometheusLabelFilters } from '../MetricCombobox';
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ import { TimeRange } from '@grafana/data';
|
||||
import { BackendSrvRequest } from '@grafana/runtime';
|
||||
|
||||
import { getDefaultCacheHeaders } from './caching';
|
||||
import { DEFAULT_SERIES_LIMIT } from './components/metrics-browser/types';
|
||||
import { DEFAULT_SERIES_LIMIT, EMPTY_SELECTOR, MATCH_ALL_LABELS, METRIC_LABEL } from './constants';
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
import { removeQuotesIfExist } from './language_provider';
|
||||
import { getRangeSnapInterval, processHistogramMetrics } from './language_utils';
|
||||
import { buildVisualQueryFromString } from './querybuilder/parsing';
|
||||
import { EMPTY_MATCHER, MATCH_ALL_LABELS, METRIC_LABEL, PrometheusCacheLevel } from './types';
|
||||
import { PrometheusCacheLevel } from './types';
|
||||
import { escapeForUtf8Support, utf8Support } from './utf8_support';
|
||||
|
||||
type PrometheusSeriesResponse = Array<{ [key: string]: string }>;
|
||||
@@ -66,7 +66,7 @@ export abstract class BaseResourceClient {
|
||||
* @param {string} limit - Maximum number of series to return
|
||||
*/
|
||||
public querySeries = async (timeRange: TimeRange, match: string, limit: string = DEFAULT_SERIES_LIMIT) => {
|
||||
const effectiveMatch = !match || match === EMPTY_MATCHER ? MATCH_ALL_LABELS : match;
|
||||
const effectiveMatch = !match || match === EMPTY_SELECTOR ? MATCH_ALL_LABELS : match;
|
||||
const timeParams = this.datasource.getTimeRangeParams(timeRange);
|
||||
const searchParams = { ...timeParams, 'match[]': effectiveMatch, limit };
|
||||
return await this.requestSeries('/api/v1/series', searchParams, getDefaultCacheHeaders(this.datasource.cacheLevel));
|
||||
@@ -186,7 +186,7 @@ export class SeriesApiClient extends BaseResourceClient implements ResourceApiCl
|
||||
match?: string,
|
||||
limit: string = DEFAULT_SERIES_LIMIT
|
||||
): Promise<string[]> => {
|
||||
const effectiveMatch = !match || match === EMPTY_MATCHER ? MATCH_ALL_LABELS : match;
|
||||
const effectiveMatch = !match || match === EMPTY_SELECTOR ? MATCH_ALL_LABELS : match;
|
||||
const maybeCachedKeys = this._cache.getLabelKeys(timeRange, effectiveMatch, limit);
|
||||
if (maybeCachedKeys) {
|
||||
return maybeCachedKeys;
|
||||
@@ -205,7 +205,7 @@ export class SeriesApiClient extends BaseResourceClient implements ResourceApiCl
|
||||
limit: string = DEFAULT_SERIES_LIMIT
|
||||
): Promise<string[]> => {
|
||||
let effectiveMatch = '';
|
||||
if (!match || match === EMPTY_MATCHER) {
|
||||
if (!match || match === EMPTY_SELECTOR) {
|
||||
// Just and empty matcher {} or no matcher
|
||||
effectiveMatch = `{${utf8Support(removeQuotesIfExist(labelKey))}!=""}`;
|
||||
} else {
|
||||
|
||||
@@ -189,8 +189,3 @@ export type RecordingRuleIdentifier = {
|
||||
identifier?: string;
|
||||
identifierValue?: string;
|
||||
};
|
||||
|
||||
export const EMPTY_MATCHER = '{}';
|
||||
export const MATCH_ALL_LABELS_STR = '__name__!=""';
|
||||
export const MATCH_ALL_LABELS = '{__name__!=""}';
|
||||
export const METRIC_LABEL = '__name__';
|
||||
|
||||
Reference in New Issue
Block a user