mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Add filtering to SD page and improve state processing
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
4ce71af1b9
commit
697327a51d
|
@ -41,6 +41,14 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.healthInfo {
|
||||||
|
background-color: light-dark(
|
||||||
|
var(--mantine-color-blue-1),
|
||||||
|
var(--mantine-color-blue-9)
|
||||||
|
);
|
||||||
|
color: light-dark(var(--mantine-color-blue-9), var(--mantine-color-blue-1));
|
||||||
|
}
|
||||||
|
|
||||||
.healthUnknown {
|
.healthUnknown {
|
||||||
background-color: light-dark(
|
background-color: light-dark(
|
||||||
var(--mantine-color-gray-2),
|
var(--mantine-color-gray-2),
|
||||||
|
|
|
@ -14,7 +14,12 @@ import {
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
||||||
|
|
||||||
import { StringParam, useQueryParam, withDefault } from "use-query-params";
|
import {
|
||||||
|
ArrayParam,
|
||||||
|
StringParam,
|
||||||
|
useQueryParam,
|
||||||
|
withDefault,
|
||||||
|
} from "use-query-params";
|
||||||
import ErrorBoundary from "../../components/ErrorBoundary";
|
import ErrorBoundary from "../../components/ErrorBoundary";
|
||||||
import ScrapePoolList from "./ServiceDiscoveryPoolsList";
|
import ScrapePoolList from "./ServiceDiscoveryPoolsList";
|
||||||
import { useSuspenseAPIQuery } from "../../api/api";
|
import { useSuspenseAPIQuery } from "../../api/api";
|
||||||
|
@ -23,6 +28,8 @@ import {
|
||||||
setCollapsedPools,
|
setCollapsedPools,
|
||||||
setShowLimitAlert,
|
setShowLimitAlert,
|
||||||
} from "../../state/serviceDiscoveryPageSlice";
|
} from "../../state/serviceDiscoveryPageSlice";
|
||||||
|
import { StateMultiSelect } from "../../components/StateMultiSelect";
|
||||||
|
import badgeClasses from "../../Badge.module.css";
|
||||||
|
|
||||||
export const targetPoolDisplayLimit = 20;
|
export const targetPoolDisplayLimit = 20;
|
||||||
|
|
||||||
|
@ -38,9 +45,13 @@ export default function ServiceDiscoveryPage() {
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [scrapePool, setScrapePool] = useQueryParam("scrapePool", StringParam);
|
const [scrapePool, setScrapePool] = useQueryParam("pool", StringParam);
|
||||||
|
const [stateFilter, setStateFilter] = useQueryParam(
|
||||||
|
"state",
|
||||||
|
withDefault(ArrayParam, [])
|
||||||
|
);
|
||||||
const [searchFilter, setSearchFilter] = useQueryParam(
|
const [searchFilter, setSearchFilter] = useQueryParam(
|
||||||
"searchFilter",
|
"search",
|
||||||
withDefault(StringParam, "")
|
withDefault(StringParam, "")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -76,6 +87,15 @@ export default function ServiceDiscoveryPage() {
|
||||||
}}
|
}}
|
||||||
searchable
|
searchable
|
||||||
/>
|
/>
|
||||||
|
<StateMultiSelect
|
||||||
|
options={["active", "dropped"]}
|
||||||
|
optionClass={(o) =>
|
||||||
|
o === "active" ? badgeClasses.healthOk : badgeClasses.healthInfo
|
||||||
|
}
|
||||||
|
placeholder="Filter by state"
|
||||||
|
values={(stateFilter?.filter((v) => v !== null) as string[]) || []}
|
||||||
|
onChange={(values) => setStateFilter(values)}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
flex={1}
|
flex={1}
|
||||||
leftSection={<IconSearch size={14} />}
|
leftSection={<IconSearch size={14} />}
|
||||||
|
@ -118,6 +138,7 @@ export default function ServiceDiscoveryPage() {
|
||||||
<ScrapePoolList
|
<ScrapePoolList
|
||||||
poolNames={scrapePools}
|
poolNames={scrapePools}
|
||||||
selectedPool={(limited && scrapePools[0]) || scrapePool || null}
|
selectedPool={(limited && scrapePools[0]) || scrapePool || null}
|
||||||
|
stateFilter={stateFilter as string[]}
|
||||||
searchFilter={searchFilter}
|
searchFilter={searchFilter}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
Target,
|
Target,
|
||||||
TargetsResult,
|
TargetsResult,
|
||||||
} from "../../api/responseTypes/targets";
|
} from "../../api/responseTypes/targets";
|
||||||
import { FC } from "react";
|
import { FC, useMemo } from "react";
|
||||||
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
import { useAppDispatch, useAppSelector } from "../../state/hooks";
|
||||||
import {
|
import {
|
||||||
setCollapsedPools,
|
setCollapsedPools,
|
||||||
|
@ -62,10 +62,12 @@ const droppedTargetKVSearch = new KVSearch<DroppedTarget>({
|
||||||
indexedKeys: ["discoveredLabels", ["discoveredLabels", /.*/]],
|
indexedKeys: ["discoveredLabels", ["discoveredLabels", /.*/]],
|
||||||
});
|
});
|
||||||
|
|
||||||
const groupTargets = (
|
const buildPoolsData = (
|
||||||
poolNames: string[],
|
poolNames: string[],
|
||||||
activeTargets: Target[],
|
activeTargets: Target[],
|
||||||
droppedTargets: DroppedTarget[]
|
droppedTargets: DroppedTarget[],
|
||||||
|
search: string,
|
||||||
|
stateFilter: (string | null)[]
|
||||||
): ScrapePools => {
|
): ScrapePools => {
|
||||||
const pools: ScrapePools = {};
|
const pools: ScrapePools = {};
|
||||||
|
|
||||||
|
@ -88,8 +90,19 @@ const groupTargets = (
|
||||||
|
|
||||||
pool.active++;
|
pool.active++;
|
||||||
pool.total++;
|
pool.total++;
|
||||||
|
}
|
||||||
|
|
||||||
pool.targets.push({
|
const filteredActiveTargets =
|
||||||
|
stateFilter.length !== 0 && !stateFilter.includes("active")
|
||||||
|
? []
|
||||||
|
: search === ""
|
||||||
|
? activeTargets
|
||||||
|
: activeTargetKVSearch
|
||||||
|
.filter(search, activeTargets)
|
||||||
|
.map((value) => value.original);
|
||||||
|
|
||||||
|
for (const target of filteredActiveTargets) {
|
||||||
|
pools[target.scrapePool].targets.push({
|
||||||
discoveredLabels: target.discoveredLabels,
|
discoveredLabels: target.discoveredLabels,
|
||||||
labels: target.labels,
|
labels: target.labels,
|
||||||
isDropped: false,
|
isDropped: false,
|
||||||
|
@ -107,30 +120,39 @@ const groupTargets = (
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.total++;
|
pool.total++;
|
||||||
|
}
|
||||||
|
|
||||||
pool.targets.push({
|
const filteredDroppedTargets =
|
||||||
|
stateFilter.length !== 0 && !stateFilter.includes("dropped")
|
||||||
|
? []
|
||||||
|
: search === ""
|
||||||
|
? droppedTargets
|
||||||
|
: droppedTargetKVSearch
|
||||||
|
.filter(search, droppedTargets)
|
||||||
|
.map((value) => value.original);
|
||||||
|
|
||||||
|
for (const target of filteredDroppedTargets) {
|
||||||
|
pools[target.discoveredLabels.job].targets.push({
|
||||||
discoveredLabels: target.discoveredLabels,
|
discoveredLabels: target.discoveredLabels,
|
||||||
isDropped: true,
|
isDropped: true,
|
||||||
labels: {},
|
labels: {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (const target of shownTargets) {
|
|
||||||
// pools[target.scrapePool].targets.push(target);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return pools;
|
return pools;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ScrapePoolListProp = {
|
type ScrapePoolListProp = {
|
||||||
poolNames: string[];
|
poolNames: string[];
|
||||||
selectedPool: string | null;
|
selectedPool: string | null;
|
||||||
|
stateFilter: string[];
|
||||||
searchFilter: string;
|
searchFilter: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ScrapePoolList: FC<ScrapePoolListProp> = ({
|
const ScrapePoolList: FC<ScrapePoolListProp> = ({
|
||||||
poolNames,
|
poolNames,
|
||||||
selectedPool,
|
selectedPool,
|
||||||
|
stateFilter,
|
||||||
searchFilter,
|
searchFilter,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
@ -157,24 +179,23 @@ const ScrapePoolList: FC<ScrapePoolListProp> = ({
|
||||||
|
|
||||||
const [debouncedSearch] = useDebouncedValue<string>(searchFilter, 250);
|
const [debouncedSearch] = useDebouncedValue<string>(searchFilter, 250);
|
||||||
|
|
||||||
// TODO: Memoize all this computation, especially groupTargets().
|
const allPools = useMemo(
|
||||||
// const search = debouncedSearch.trim();
|
() =>
|
||||||
// const healthFilteredTargets = activeTargets.filter(
|
buildPoolsData(
|
||||||
// (target) =>
|
selectedPool ? [selectedPool] : poolNames,
|
||||||
// healthFilter.length === 0 ||
|
activeTargets,
|
||||||
// healthFilter.includes(target.health.toLowerCase())
|
droppedTargets,
|
||||||
// );
|
debouncedSearch,
|
||||||
// const filteredTargets =
|
stateFilter
|
||||||
// search === ""
|
),
|
||||||
// ? healthFilteredTargets
|
[
|
||||||
// : kvSearch
|
selectedPool,
|
||||||
// .filter(search, healthFilteredTargets)
|
poolNames,
|
||||||
// .map((value) => value.original);
|
activeTargets,
|
||||||
|
droppedTargets,
|
||||||
const allPools = groupTargets(
|
debouncedSearch,
|
||||||
selectedPool ? [selectedPool] : poolNames,
|
stateFilter,
|
||||||
activeTargets,
|
]
|
||||||
droppedTargets
|
|
||||||
);
|
);
|
||||||
const allPoolNames = Object.keys(allPools);
|
const allPoolNames = Object.keys(allPools);
|
||||||
const shownPoolNames = showEmptyPools
|
const shownPoolNames = showEmptyPools
|
||||||
|
@ -240,17 +261,22 @@ const ScrapePoolList: FC<ScrapePoolListProp> = ({
|
||||||
<RingProgress
|
<RingProgress
|
||||||
size={25}
|
size={25}
|
||||||
thickness={5}
|
thickness={5}
|
||||||
sections={[
|
sections={
|
||||||
{
|
pool.total === 0
|
||||||
value: (pool.active / pool.total) * 100,
|
? []
|
||||||
color: "green.4",
|
: [
|
||||||
},
|
{
|
||||||
{
|
value: (pool.active / pool.total) * 100,
|
||||||
value:
|
color: "green.4",
|
||||||
((pool.total - pool.active) / pool.total) * 100,
|
},
|
||||||
color: "grape.4",
|
{
|
||||||
},
|
value:
|
||||||
]}
|
((pool.total - pool.active) / pool.total) *
|
||||||
|
100,
|
||||||
|
color: "blue.6",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
|
@ -254,22 +254,24 @@ const ScrapePoolList: FC<ScrapePoolListProp> = ({
|
||||||
<RingProgress
|
<RingProgress
|
||||||
size={25}
|
size={25}
|
||||||
thickness={5}
|
thickness={5}
|
||||||
sections={[
|
sections={
|
||||||
{
|
pool.count === 0
|
||||||
value: (pool.upCount / pool.count) * 100,
|
? []
|
||||||
color: "green.4",
|
: [
|
||||||
},
|
{
|
||||||
// Important that gray is the middle one, since the middle one seems to be
|
value: (pool.upCount / pool.count) * 100,
|
||||||
// the default color if all three values are 0 (empty pool = gray).
|
color: "green.4",
|
||||||
{
|
},
|
||||||
value: (pool.unknownCount / pool.count) * 100,
|
{
|
||||||
color: "gray.4",
|
value: (pool.unknownCount / pool.count) * 100,
|
||||||
},
|
color: "gray.4",
|
||||||
{
|
},
|
||||||
value: (pool.downCount / pool.count) * 100,
|
{
|
||||||
color: "red.5",
|
value: (pool.downCount / pool.count) * 100,
|
||||||
},
|
color: "red.5",
|
||||||
]}
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
Loading…
Reference in a new issue