Skip to content

Commit

Permalink
update Prometheus plugin with latest from main
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Bernal <gabrielbernalp@gmail.com>
  • Loading branch information
jgbernalp committed Dec 16, 2024
1 parent a55ef68 commit 90d0847
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 86 deletions.
6 changes: 3 additions & 3 deletions Prometheus/src/components/PromQLEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { PromQLExtension, CompleteConfiguration } from '@prometheus-io/codemirro
import { EditorView } from '@codemirror/view';
import { useTheme, CircularProgress, InputLabel, Stack, IconButton, Tooltip } from '@mui/material';
import FileTreeIcon from 'mdi-material-ui/FileTree';
import { useMemo, useState } from 'react';
import { ReactElement, useMemo, useState } from 'react';
import { ErrorAlert } from '@perses-dev/components';
import CloseIcon from 'mdi-material-ui/Close';
import { useReplaceVariablesInString } from '@perses-dev/plugin-system';
Expand All @@ -42,7 +42,7 @@ export type PromQLEditorProps = {
datasource: PrometheusDatasourceSelector;
} & Omit<ReactCodeMirrorProps, 'theme' | 'extensions'>;

export function PromQLEditor({ completeConfig, datasource, ...rest }: PromQLEditorProps) {
export function PromQLEditor({ completeConfig, datasource, ...rest }: PromQLEditorProps): ReactElement {
const theme = useTheme();
const isDarkMode = theme.palette.mode === 'dark';
const [isTreeViewVisible, setTreeViewVisible] = useState(false);
Expand All @@ -63,7 +63,7 @@ export function PromQLEditor({ completeConfig, datasource, ...rest }: PromQLEdit
const { data: parseQueryResponse, isLoading, error } = useParseQuery(queryExpr ?? '', datasource, isTreeViewVisible);
const errorMessage = useMemo(() => getErrMessage(error), [error]);

const handleShowTreeView = () => {
const handleShowTreeView = (): void => {
setTreeViewVisible(!isTreeViewVisible);
};

Expand Down
8 changes: 6 additions & 2 deletions Prometheus/src/components/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@

import { useDatasourceClient } from '@perses-dev/plugin-system';
import { DatasourceSelector } from '@perses-dev/core';
import { useQuery } from '@tanstack/react-query';
import { useQuery, UseQueryResult } from '@tanstack/react-query';
import { ParseQueryRequestParameters, ParseQueryResponse, PrometheusClient } from '../model';

export function useParseQuery(content: string, datasource: DatasourceSelector, enabled?: boolean) {
export function useParseQuery(
content: string,
datasource: DatasourceSelector,
enabled?: boolean
): UseQueryResult<ParseQueryResponse> {
const { data: client } = useDatasourceClient<PrometheusClient>(datasource);

return useQuery<ParseQueryResponse>({
Expand Down
2 changes: 1 addition & 1 deletion Prometheus/src/components/promql/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ export const getNodeChildren = (node: ASTNode): ASTNode[] => {
}
};

export const escapeString = (str: string) => {
export const escapeString = (str: string): string => {
return str.replace(/([\\"])/g, '\\$1');
};
33 changes: 25 additions & 8 deletions Prometheus/src/model/prometheus-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export interface QueryOptions {
* Calls the `/-/healthy` endpoint to check if the datasource is healthy.
*/
export function healthCheck(queryOptions: QueryOptions) {
return async () => {
return async (): Promise<boolean> => {
const url = `${queryOptions.datasourceUrl}/-/healthy`;

try {
Expand All @@ -71,21 +71,30 @@ export function healthCheck(queryOptions: QueryOptions) {
/**
* Calls the `/api/v1/query` endpoint to get metrics data.
*/
export function instantQuery(params: InstantQueryRequestParameters, queryOptions: QueryOptions) {
export function instantQuery(
params: InstantQueryRequestParameters,
queryOptions: QueryOptions
): Promise<InstantQueryResponse> {
return fetchWithPost<InstantQueryRequestParameters, InstantQueryResponse>('/api/v1/query', params, queryOptions);
}

/**
* Calls the `/api/v1/query_range` endpoint to get metrics data.
*/
export function rangeQuery(params: RangeQueryRequestParameters, queryOptions: QueryOptions) {
export function rangeQuery(
params: RangeQueryRequestParameters,
queryOptions: QueryOptions
): Promise<RangeQueryResponse> {
return fetchWithPost<RangeQueryRequestParameters, RangeQueryResponse>('/api/v1/query_range', params, queryOptions);
}

/**
* Calls the `/api/v1/labels` endpoint to get a list of label names.
*/
export function labelNames(params: LabelNamesRequestParameters, queryOptions: QueryOptions) {
export function labelNames(
params: LabelNamesRequestParameters,
queryOptions: QueryOptions
): Promise<LabelNamesResponse> {
return fetchWithPost<LabelNamesRequestParameters, LabelNamesResponse>('/api/v1/labels', params, queryOptions);
}

Expand Down Expand Up @@ -140,7 +149,11 @@ export function parseQuery(
return fetchWithPost<ParseQueryRequestParameters, ParseQueryResponse>(apiURI, params, queryOptions);
}

function fetchWithGet<T extends RequestParams<T>, TResponse>(apiURI: string, params: T, queryOptions: QueryOptions) {
function fetchWithGet<T extends RequestParams<T>, TResponse>(
apiURI: string,
params: T,
queryOptions: QueryOptions
): Promise<TResponse> {
const { datasourceUrl, headers } = queryOptions;

let url = `${datasourceUrl}${apiURI}`;
Expand All @@ -151,7 +164,11 @@ function fetchWithGet<T extends RequestParams<T>, TResponse>(apiURI: string, par
return fetchJson<TResponse>(url, { method: 'GET', headers });
}

function fetchWithPost<T extends RequestParams<T>, TResponse>(apiURI: string, params: T, queryOptions: QueryOptions) {
function fetchWithPost<T extends RequestParams<T>, TResponse>(
apiURI: string,
params: T,
queryOptions: QueryOptions
): Promise<TResponse> {
const { datasourceUrl, headers } = queryOptions;

const url = `${datasourceUrl}${apiURI}`;
Expand All @@ -178,7 +195,7 @@ type RequestParams<T> = {
/**
* Creates URLSearchParams from a request params object.
*/
function createSearchParams<T extends RequestParams<T>>(params: T) {
function createSearchParams<T extends RequestParams<T>>(params: T): URLSearchParams {
const searchParams = new URLSearchParams();
for (const key in params) {
const value: ParamValue = params[key];
Expand All @@ -204,7 +221,7 @@ function createSearchParams<T extends RequestParams<T>>(params: T) {
/**
* Fetch JSON and parse warnings for query inspector
*/
export async function fetchResults<T>(...args: Parameters<typeof global.fetch>) {
export async function fetchResults<T>(...args: Parameters<typeof global.fetch>): Promise<T> {
const response = await fetch(...args);
const json: T = await response.json();
return { ...json, rawResponse: response };
Expand Down
2 changes: 1 addition & 1 deletion Prometheus/src/model/prometheus-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const DEFAULT_PROM: PrometheusDatasourceSelector = { kind: PROM_DATASOURC
/**
* Returns true if the provided PrometheusDatasourceSelector is the default one.
*/
export function isDefaultPromSelector(selector: PrometheusDatasourceSelector) {
export function isDefaultPromSelector(selector: PrometheusDatasourceSelector): boolean {
return selector.name === undefined;
}

Expand Down
11 changes: 8 additions & 3 deletions Prometheus/src/model/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface PrometheusTimeRange {
/**
* Converts an AbsoluteTimeRange to Prometheus time in Unix time (i.e. in seconds).
*/
export function getPrometheusTimeRange(timeRange: AbsoluteTimeRange) {
export function getPrometheusTimeRange(timeRange: AbsoluteTimeRange): { start: number; end: number } {
const { start, end } = timeRange;
return {
start: Math.ceil(getUnixTime(start)),
Expand All @@ -40,7 +40,12 @@ const MAX_PROM_DATA_POINTS = 10000;
* width of a visualization where the data will be graphed), any minimum step/resolution set by the user, and a "safe"
* step based on the max data points we want to allow returning from a Prom query.
*/
export function getRangeStep(timeRange: PrometheusTimeRange, minStepSeconds = 15, resolution = 1, suggestedStepMs = 0) {
export function getRangeStep(
timeRange: PrometheusTimeRange,
minStepSeconds = 15,
resolution = 1,
suggestedStepMs = 0
): number {
const suggestedStepSeconds = suggestedStepMs / 1000;
const queryRangeSeconds = timeRange.end - timeRange.start;

Expand All @@ -55,7 +60,7 @@ export function getRangeStep(timeRange: PrometheusTimeRange, minStepSeconds = 15
/**
* Converts a DurationString to seconds, rounding down.
*/
export function getDurationStringSeconds(durationString?: DurationString) {
export function getDurationStringSeconds(durationString?: DurationString): number | undefined {
if (!durationString) return undefined;

const duration = parseDurationString(durationString);
Expand Down
3 changes: 2 additions & 1 deletion Prometheus/src/plugins/MatcherEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
import { Stack, TextField, Button, Box, IconButton } from '@mui/material';
import { produce } from 'immer';
import TrashIcon from 'mdi-material-ui/TrashCan';
import { ReactElement } from 'react';

type MatcherEditorProps = {
matchers: string[];
onChange: (matchers: string[]) => void;
isReadonly?: boolean;
};

export function MatcherEditor({ matchers, onChange, isReadonly }: MatcherEditorProps) {
export function MatcherEditor({ matchers, onChange, isReadonly }: MatcherEditorProps): ReactElement {
return (
<Stack spacing={1} mb={2}>
{matchers.map((matcher, index) => (
Expand Down
12 changes: 8 additions & 4 deletions Prometheus/src/plugins/PrometheusDatasourceEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import { DurationString, RequestHeaders } from '@perses-dev/core';
import { OptionsEditorRadios } from '@perses-dev/plugin-system';
import { Grid, IconButton, MenuItem, TextField, Typography } from '@mui/material';
import React, { Fragment, useState } from 'react';
import React, { Fragment, ReactElement, useState } from 'react';
import { produce } from 'immer';
import { Controller } from 'react-hook-form';
import MinusIcon from 'mdi-material-ui/Minus';
Expand All @@ -27,14 +27,18 @@ export interface PrometheusDatasourceEditorProps {
isReadonly?: boolean;
}

export function PrometheusDatasourceEditor(props: PrometheusDatasourceEditorProps) {
export function PrometheusDatasourceEditor(props: PrometheusDatasourceEditorProps): ReactElement {
const { value, onChange, isReadonly } = props;
const strDirect = 'Direct access';
const strProxy = 'Proxy';

// utilitary function used for headers when renaming a property
// -> TODO it would be cleaner to manipulate headers as an intermediary list instead, to avoid doing this.
const buildNewHeaders = (oldHeaders: RequestHeaders | undefined, oldName: string, newName: string) => {
const buildNewHeaders = (
oldHeaders: RequestHeaders | undefined,
oldName: string,
newName: string
): RequestHeaders | undefined => {
if (oldHeaders === undefined) return oldHeaders;
const keys = Object.keys(oldHeaders);
const newHeaders = keys.reduce<Record<string, string>>((acc, val) => {
Expand Down Expand Up @@ -476,7 +480,7 @@ export function PrometheusDatasourceEditor(props: PrometheusDatasourceEditorProp
const [previousSpecProxy, setPreviousSpecProxy] = useState(initialSpecProxy);

// When changing mode, remove previous mode's config + append default values for the new mode.
const handleModeChange = (v: number) => {
const handleModeChange = (v: number): void => {
if (tabs[v]?.label === strDirect) {
setPreviousSpecProxy(value);
onChange(previousSpecDirect);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import { produce } from 'immer';
import { DatasourceSelect, DatasourceSelectProps, useDatasource, useDatasourceClient } from '@perses-dev/plugin-system';
import { FormControl, InputLabel, Stack, TextField } from '@mui/material';
import { ReactElement } from 'react';
import {
DEFAULT_PROM,
DurationString,
Expand All @@ -34,7 +35,7 @@ import {
/**
* The options editor component for editing a PrometheusTimeSeriesQuery's spec.
*/
export function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQueryEditorProps) {
export function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQueryEditorProps): ReactElement {
const { onChange, value } = props;
const { datasource } = value;
const selectedDatasource = datasource ?? DEFAULT_PROM;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const getDatasource: jest.Mock = jest.fn((): DatasourceSpec<PrometheusDatasource
};
});

const createStubContext = () => {
const createStubContext = (): TimeSeriesQueryContext => {
const stubTimeSeriesContext: TimeSeriesQueryContext = {
datasourceStore: {
getDatasource: getDatasource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ export type PrometheusTimeSeriesQueryEditorProps = OptionsEditorProps<Prometheus
* changes with the overall spec value once the input is blurred to prevent re-running queries in the panel's preview
* every time the user types.
*/
export function useQueryState(props: PrometheusTimeSeriesQueryEditorProps) {
export function useQueryState(props: PrometheusTimeSeriesQueryEditorProps): {
query: string;
handleQueryChange: (e: string) => void;
handleQueryBlur: () => void;
} {
const { onChange, value } = props;

// Local copy of the query's value
Expand All @@ -40,13 +44,13 @@ export function useQueryState(props: PrometheusTimeSeriesQueryEditorProps) {
}

// Update our local state's copy as the user types
const handleQueryChange = (e: string) => {
const handleQueryChange = (e: string): void => {
setQuery(e);
};

// Propagate changes to the query's value when the input is blurred to avoid constantly re-running queries in the
// PanelPreview
const handleQueryBlur = () => {
const handleQueryBlur = (): void => {
setLastSyncedQuery(query);
onChange(
produce(value, (draft) => {
Expand All @@ -61,7 +65,11 @@ export function useQueryState(props: PrometheusTimeSeriesQueryEditorProps) {
/**
* Hook to manage `seriesNameFormat` state to ensure panel preview does not rerender until text input is blurred
*/
export function useFormatState(props: PrometheusTimeSeriesQueryEditorProps) {
export function useFormatState(props: PrometheusTimeSeriesQueryEditorProps): {
format: string | undefined;
handleFormatChange: (e: string) => void;
handleFormatBlur: () => void;
} {
const { onChange, value } = props;

// TODO: reusable hook or helper util instead of duplicating from useQueryState
Expand All @@ -73,12 +81,12 @@ export function useFormatState(props: PrometheusTimeSeriesQueryEditorProps) {
}

// Update our local state as the user types
const handleFormatChange = (e: string) => {
const handleFormatChange = (e: string): void => {
setFormat(e);
};

// Propagate changes to the panel preview component when seriesNameFormat TextField is blurred
const handleFormatBlur = () => {
const handleFormatBlur = (): void => {
setLastSyncedFormat(format);
onChange(
produce(value, (draft) => {
Expand All @@ -93,7 +101,11 @@ export function useFormatState(props: PrometheusTimeSeriesQueryEditorProps) {
/**
* Hook to manage `minStep` state to ensure panel preview does not rerender until text input is blurred
*/
export function useMinStepState(props: PrometheusTimeSeriesQueryEditorProps) {
export function useMinStepState(props: PrometheusTimeSeriesQueryEditorProps): {
minStep: string | undefined;
handleMinStepChange: (e: DurationString) => void;
handleMinStepBlur: () => void;
} {
const { onChange, value } = props;

// TODO: reusable hook or helper util instead of duplicating from useQueryState
Expand All @@ -105,12 +117,12 @@ export function useMinStepState(props: PrometheusTimeSeriesQueryEditorProps) {
}

// Update our local state as the user types
const handleMinStepChange = (e: DurationString) => {
const handleMinStepChange = (e: DurationString): void => {
setMinStep(e);
};

// Propagate changes to the panel preview component when minStep TextField is blurred
const handleMinStepBlur = () => {
const handleMinStepBlur = (): void => {
setLastSyncedMinStep(minStep);
onChange(
produce(value, (draft) => {
Expand Down
13 changes: 10 additions & 3 deletions Prometheus/src/plugins/prometheus-variables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from '@perses-dev/plugin-system';
import { FormControl, InputLabel, Stack, TextField } from '@mui/material';
import { produce } from 'immer';
import { ReactElement } from 'react';
import {
DEFAULT_PROM,
isDefaultPromSelector,
Expand All @@ -36,7 +37,9 @@ import {
} from './types';
import { MatcherEditor } from './MatcherEditor';

export function PrometheusLabelValuesVariableEditor(props: OptionsEditorProps<PrometheusLabelValuesVariableOptions>) {
export function PrometheusLabelValuesVariableEditor(
props: OptionsEditorProps<PrometheusLabelValuesVariableOptions>
): ReactElement {
const { onChange, value } = props;
const { datasource } = value;
const selectedDatasource = datasource ?? DEFAULT_PROM;
Expand Down Expand Up @@ -90,7 +93,9 @@ export function PrometheusLabelValuesVariableEditor(props: OptionsEditorProps<Pr
);
}

export function PrometheusLabelNamesVariableEditor(props: OptionsEditorProps<PrometheusLabelNamesVariableOptions>) {
export function PrometheusLabelNamesVariableEditor(
props: OptionsEditorProps<PrometheusLabelNamesVariableOptions>
): ReactElement {
const { onChange, value } = props;
const { datasource } = value;
const selectedDatasource = datasource ?? DEFAULT_PROM;
Expand Down Expand Up @@ -133,7 +138,9 @@ export function PrometheusLabelNamesVariableEditor(props: OptionsEditorProps<Pro
);
}

export function PrometheusPromQLVariableEditor(props: OptionsEditorProps<PrometheusPromQLVariableOptions>) {
export function PrometheusPromQLVariableEditor(
props: OptionsEditorProps<PrometheusPromQLVariableOptions>
): ReactElement {
const { onChange, value } = props;
const { datasource } = value;
const selectedDatasource = datasource ?? DEFAULT_PROM;
Expand Down
Loading

0 comments on commit 90d0847

Please sign in to comment.