mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Implement query history
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
f3f324be89
commit
a99c01b53f
|
@ -68,6 +68,7 @@ import { notifications } from "@mantine/notifications";
|
||||||
import { useSettings } from "../../state/settingsSlice";
|
import { useSettings } from "../../state/settingsSlice";
|
||||||
import MetricsExplorer from "./MetricsExplorer/MetricsExplorer";
|
import MetricsExplorer from "./MetricsExplorer/MetricsExplorer";
|
||||||
import ErrorBoundary from "../../components/ErrorBoundary";
|
import ErrorBoundary from "../../components/ErrorBoundary";
|
||||||
|
import { useAppSelector } from "../../state/hooks";
|
||||||
|
|
||||||
const promqlExtension = new PromQLExtension();
|
const promqlExtension = new PromQLExtension();
|
||||||
|
|
||||||
|
@ -127,11 +128,13 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
|
||||||
removePanel,
|
removePanel,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useComputedColorScheme();
|
const theme = useComputedColorScheme();
|
||||||
|
const { queryHistory } = useAppSelector((state) => state.queryPage);
|
||||||
const {
|
const {
|
||||||
pathPrefix,
|
pathPrefix,
|
||||||
enableAutocomplete,
|
enableAutocomplete,
|
||||||
enableSyntaxHighlighting,
|
enableSyntaxHighlighting,
|
||||||
enableLinter,
|
enableLinter,
|
||||||
|
enableQueryHistory,
|
||||||
} = useSettings();
|
} = useSettings();
|
||||||
const [expr, setExpr] = useState(initialExpr);
|
const [expr, setExpr] = useState(initialExpr);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -175,10 +178,6 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
|
||||||
|
|
||||||
const [showMetricsExplorer, setShowMetricsExplorer] = useState(false);
|
const [showMetricsExplorer, setShowMetricsExplorer] = useState(false);
|
||||||
|
|
||||||
// TODO: Implement query history.
|
|
||||||
// This is just a placeholder until query history is implemented, so disable the linter warning.
|
|
||||||
const queryHistory = useMemo<string[]>(() => [], []);
|
|
||||||
|
|
||||||
// (Re)initialize editor based on settings / setting changes.
|
// (Re)initialize editor based on settings / setting changes.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Build the dynamic part of the config.
|
// Build the dynamic part of the config.
|
||||||
|
@ -193,10 +192,17 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
|
||||||
cache: { initialMetricList: metricNames },
|
cache: { initialMetricList: metricNames },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
queryHistory
|
enableQueryHistory ? queryHistory : []
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}, [pathPrefix, metricNames, enableAutocomplete, enableLinter, queryHistory]); // TODO: Make this depend on external settings changes, maybe use dynamic config compartment again.
|
}, [
|
||||||
|
pathPrefix,
|
||||||
|
metricNames,
|
||||||
|
enableAutocomplete,
|
||||||
|
enableLinter,
|
||||||
|
enableQueryHistory,
|
||||||
|
queryHistory,
|
||||||
|
]); // TODO: Make this depend on external settings changes, maybe use dynamic config compartment again.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group align="flex-start" wrap="nowrap" gap="xs">
|
<Group align="flex-start" wrap="nowrap" gap="xs">
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import { FC, useCallback, useState } from "react";
|
import { FC, useCallback, useState } from "react";
|
||||||
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
||||||
import {
|
import {
|
||||||
|
addQueryToHistory,
|
||||||
GraphDisplayMode,
|
GraphDisplayMode,
|
||||||
GraphResolution,
|
GraphResolution,
|
||||||
removePanel,
|
removePanel,
|
||||||
|
@ -73,6 +74,10 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
|
||||||
executeQuery={(expr: string) => {
|
executeQuery={(expr: string) => {
|
||||||
setRetriggerIdx((idx) => idx + 1);
|
setRetriggerIdx((idx) => idx + 1);
|
||||||
dispatch(setExpr({ idx, expr }));
|
dispatch(setExpr({ idx, expr }));
|
||||||
|
|
||||||
|
if (!metricNames.includes(expr) && expr.trim() !== "") {
|
||||||
|
dispatch(addQueryToHistory(expr));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
removePanel={() => {
|
removePanel={() => {
|
||||||
dispatch(removePanel(idx));
|
dispatch(removePanel(idx));
|
||||||
|
|
|
@ -6,9 +6,13 @@ import {
|
||||||
} from "./targetsPageSlice";
|
} from "./targetsPageSlice";
|
||||||
import {
|
import {
|
||||||
localStorageKeyCollapsedPools as localStorageKeyServiceDiscoveryPageCollapsedPools,
|
localStorageKeyCollapsedPools as localStorageKeyServiceDiscoveryPageCollapsedPools,
|
||||||
setCollapsedPools as ServiceDiscoveryPageSetCollapsedPools,
|
setCollapsedPools as serviceDiscoveryPageSetCollapsedPools,
|
||||||
} from "./serviceDiscoveryPageSlice";
|
} from "./serviceDiscoveryPageSlice";
|
||||||
import { updateSettings } from "./settingsSlice";
|
import { updateSettings } from "./settingsSlice";
|
||||||
|
import {
|
||||||
|
addQueryToHistory,
|
||||||
|
localStorageKeyQueryHistory,
|
||||||
|
} from "./queryPageSlice";
|
||||||
|
|
||||||
const persistToLocalStorage = <T>(key: string, value: T) => {
|
const persistToLocalStorage = <T>(key: string, value: T) => {
|
||||||
localStorage.setItem(key, JSON.stringify(value));
|
localStorage.setItem(key, JSON.stringify(value));
|
||||||
|
@ -29,7 +33,7 @@ startAppListening({
|
||||||
});
|
});
|
||||||
|
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: ServiceDiscoveryPageSetCollapsedPools,
|
actionCreator: serviceDiscoveryPageSetCollapsedPools,
|
||||||
effect: ({ payload }) => {
|
effect: ({ payload }) => {
|
||||||
persistToLocalStorage(
|
persistToLocalStorage(
|
||||||
localStorageKeyServiceDiscoveryPageCollapsedPools,
|
localStorageKeyServiceDiscoveryPageCollapsedPools,
|
||||||
|
@ -38,6 +42,16 @@ startAppListening({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
startAppListening({
|
||||||
|
actionCreator: addQueryToHistory,
|
||||||
|
effect: (_, { getState }) => {
|
||||||
|
persistToLocalStorage(
|
||||||
|
localStorageKeyQueryHistory,
|
||||||
|
getState().queryPage.queryHistory
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: updateSettings,
|
actionCreator: updateSettings,
|
||||||
effect: ({ payload }) => {
|
effect: ({ payload }) => {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { randomId } from "@mantine/hooks";
|
import { randomId } from "@mantine/hooks";
|
||||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
import { encodePanelOptionsToURLParams } from "../pages/query/urlStateEncoding";
|
import { encodePanelOptionsToURLParams } from "../pages/query/urlStateEncoding";
|
||||||
|
import { initializeFromLocalStorage } from "./initializeFromLocalStorage";
|
||||||
|
|
||||||
|
export const localStorageKeyQueryHistory = "queryPage.queryHistory";
|
||||||
|
|
||||||
export enum GraphDisplayMode {
|
export enum GraphDisplayMode {
|
||||||
Lines = "lines",
|
Lines = "lines",
|
||||||
|
@ -68,6 +71,7 @@ export type Panel = {
|
||||||
|
|
||||||
interface QueryPageState {
|
interface QueryPageState {
|
||||||
panels: Panel[];
|
panels: Panel[];
|
||||||
|
queryHistory: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const newDefaultPanel = (): Panel => ({
|
export const newDefaultPanel = (): Panel => ({
|
||||||
|
@ -87,6 +91,10 @@ export const newDefaultPanel = (): Panel => ({
|
||||||
|
|
||||||
const initialState: QueryPageState = {
|
const initialState: QueryPageState = {
|
||||||
panels: [newDefaultPanel()],
|
panels: [newDefaultPanel()],
|
||||||
|
queryHistory: initializeFromLocalStorage<string[]>(
|
||||||
|
localStorageKeyQueryHistory,
|
||||||
|
[]
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateURL = (panels: Panel[]) => {
|
const updateURL = (panels: Panel[]) => {
|
||||||
|
@ -116,6 +124,12 @@ export const queryPageSlice = createSlice({
|
||||||
state.panels[payload.idx].expr = payload.expr;
|
state.panels[payload.idx].expr = payload.expr;
|
||||||
updateURL(state.panels);
|
updateURL(state.panels);
|
||||||
},
|
},
|
||||||
|
addQueryToHistory: (state, { payload: query }: PayloadAction<string>) => {
|
||||||
|
state.queryHistory = [
|
||||||
|
query,
|
||||||
|
...state.queryHistory.filter((q) => q !== query),
|
||||||
|
].slice(0, 50);
|
||||||
|
},
|
||||||
setVisualizer: (
|
setVisualizer: (
|
||||||
state,
|
state,
|
||||||
{ payload }: PayloadAction<{ idx: number; visualizer: Visualizer }>
|
{ payload }: PayloadAction<{ idx: number; visualizer: Visualizer }>
|
||||||
|
@ -126,7 +140,14 @@ export const queryPageSlice = createSlice({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setPanels, addPanel, removePanel, setExpr, setVisualizer } =
|
export const {
|
||||||
queryPageSlice.actions;
|
setPanels,
|
||||||
|
addPanel,
|
||||||
|
removePanel,
|
||||||
|
setExpr,
|
||||||
|
addQueryToHistory,
|
||||||
|
setShowTree,
|
||||||
|
setVisualizer,
|
||||||
|
} = queryPageSlice.actions;
|
||||||
|
|
||||||
export default queryPageSlice.reducer;
|
export default queryPageSlice.reducer;
|
||||||
|
|
Loading…
Reference in a new issue