diff --git a/src/components/SuccessRateContextProvider.tsx b/src/components/SuccessRateContextProvider.tsx index e7353fa0e..303351a5f 100644 --- a/src/components/SuccessRateContextProvider.tsx +++ b/src/components/SuccessRateContextProvider.tsx @@ -1,11 +1,12 @@ import React, { PropsWithChildren, useContext, useEffect, useState } from 'react'; -import { Check } from 'types'; +import { Check, Probe } from 'types'; import { queryMetric } from 'utils'; import { InstanceContext } from 'contexts/InstanceContext'; import { SuccessRates, SuccessRateContext, SuccessRateTypes, SuccessRate } from 'contexts/SuccessRateContext'; interface Props { - checks: Check[]; + checks?: Check[]; + probes?: Probe[]; } const values: SuccessRates = { @@ -16,6 +17,7 @@ const values: SuccessRates = { type SeedRequestMetric = { instance: string; job: string; + probe: string; }; type SeedRequestValue = [number, string]; @@ -27,7 +29,63 @@ type SeedRequestItem = { type SeedRequestResponse = SeedRequestItem[]; -export function SuccessRateContextProvider({ checks, children }: PropsWithChildren) { +const parseCheckResults = (checks: Check[] | undefined, data: any) => { + if (!checks) { + return; + } + + const response = data as SeedRequestResponse; + const resultsPerCheck = checks.reduce((acc, check) => { + if (!check.id) { + return acc; + } + acc[check.id] = undefined; + return acc; + }, {}); + + response.forEach((item) => { + const check = checks?.find((check) => check.job === item.metric.job && check.target === item.metric.instance); + if (check && check.id) { + const returnedValue = item.value?.[1]; + if (returnedValue !== undefined) { + const float = parseFloat(returnedValue); + resultsPerCheck[check.id] = float; + } + } + }); + + return resultsPerCheck; +}; + +const parseProbeResults = (probes: Probe[] | undefined, data: any) => { + if (!probes) { + return {}; + } + + const response = data as SeedRequestResponse; + const resultsPerCheck = probes.reduce((acc, probe) => { + if (!probe.id) { + return acc; + } + acc[probe.id] = undefined; + return acc; + }, {}); + + response.forEach((item) => { + const check = probes?.find((probe) => probe.name === item.metric.probe); + if (check && check.id) { + const returnedValue = item.value?.[1]; + if (returnedValue !== undefined) { + const float = parseFloat(returnedValue); + resultsPerCheck[check.id] = float; + } + } + }); + + return resultsPerCheck; +}; + +export function SuccessRateContextProvider({ checks, probes, children }: PropsWithChildren) { const { instance } = useContext(InstanceContext); const [successRateValues, setSuccessRate] = useState(values); const [loading, setLoading] = useState(true); @@ -49,11 +107,25 @@ export function SuccessRateContextProvider({ checks, children }: PropsWithChildr useEffect(() => { const getSuccessRates = async () => { setLoading(true); - const uptimeQuery = `sum(rate(probe_all_success_sum[3h])) by (job, instance) / sum(rate(probe_all_success_count[3h])) by (job, instance)`; + const checkUptimeQuery = + 'sum(rate(probe_all_success_sum[3h])) by (job, instance) / sum(rate(probe_all_success_count[3h])) by (job, instance)'; + const probeUptimeQuery = + 'sum(rate(probe_all_success_sum[3h])) by (probe) / sum(rate(probe_all_success_count[3h])) by (probe)'; + + const successRateType = checks ? SuccessRateTypes.Checks : SuccessRateTypes.Probes; + + const uptimeQuery = successRateType === SuccessRateTypes.Checks ? checkUptimeQuery : probeUptimeQuery; + const url = instance?.api?.getMetricsDS()?.url; - if (!url || !checks.length) { + + if ( + !url || + (successRateType === SuccessRateTypes.Checks && !checks?.length) || + (successRateType === SuccessRateTypes.Probes && !probes?.length) + ) { return; } + const now = Math.floor(Date.now() / 1000); const start = now - 60 * 60 * 3; const options = { @@ -63,35 +135,17 @@ export function SuccessRateContextProvider({ checks, children }: PropsWithChildr }; const { error, data } = await queryMetric(url, uptimeQuery, options); + const resultsByType = + successRateType === SuccessRateTypes.Checks ? parseCheckResults(checks, data) : parseProbeResults(probes, data); + if (error || !data) { setLoading(false); return; } - const resultsPerCheck = checks.reduce((acc, check) => { - if (!check.id) { - return acc; - } - acc[check.id] = undefined; - return acc; - }, {}); - - const response = data as SeedRequestResponse; - - response.forEach((item) => { - const check = checks?.find((check) => check.job === item.metric.job && check.target === item.metric.instance); - if (check && check.id) { - const returnedValue = item.value?.[1]; - if (returnedValue !== undefined) { - const float = parseFloat(returnedValue); - resultsPerCheck[check.id] = float; - } - } - }); - setSuccessRate((state) => ({ ...state, - [SuccessRateTypes.Checks]: resultsPerCheck, + [successRateType]: resultsByType, })); setLoading(false); }; @@ -104,7 +158,7 @@ export function SuccessRateContextProvider({ checks, children }: PropsWithChildr }, 60 * 1000); return () => clearInterval(interval); - }, [checks, instance.api]); + }, [checks, instance.api, probes]); return ( diff --git a/src/page/ProbesPage.tsx b/src/page/ProbesPage.tsx index 91538a644..33a0dbc86 100644 --- a/src/page/ProbesPage.tsx +++ b/src/page/ProbesPage.tsx @@ -7,6 +7,7 @@ import { getLocationSrv } from '@grafana/runtime'; import ProbeEditor from 'components/ProbeEditor'; import { InstanceContext } from 'contexts/InstanceContext'; import { ProbeList } from 'components/ProbeList'; +import { SuccessRateContextProvider } from 'components/SuccessRateContextProvider'; interface Props { id?: string; @@ -76,5 +77,9 @@ export const ProbesPage = ({ id }: Props) => { } as Probe; return ; } - return setAddingNew(true)} onSelectProbe={onSelectProbe} />; + return ( + + setAddingNew(true)} onSelectProbe={onSelectProbe} /> + + ); };