diff --git a/pkg/model/fields/fields.go b/pkg/model/fields/fields.go index d8e5281c5..64d0b2163 100644 --- a/pkg/model/fields/fields.go +++ b/pkg/model/fields/fields.go @@ -1,55 +1,57 @@ package fields const ( - Src = "Src" - Dst = "Dst" - Namespace = "K8S_Namespace" - SrcNamespace = Src + Namespace - DstNamespace = Dst + Namespace - OwnerType = "K8S_OwnerType" - SrcOwnerType = Src + OwnerType - DstOwnerType = Dst + OwnerType - OwnerName = "K8S_OwnerName" - SrcOwnerName = Src + OwnerName - DstOwnerName = Dst + OwnerName - Type = "K8S_Type" - SrcType = Src + Type - DstType = Dst + Type - Name = "K8S_Name" - SrcName = Src + Name - DstName = Dst + Name - Addr = "Addr" - SrcAddr = Src + Addr - DstAddr = Dst + Addr - Port = "Port" - SrcPort = Src + Port - DstPort = Dst + Port - HostIP = "K8S_HostIP" - SrcHostIP = Src + HostIP - DstHostIP = Dst + HostIP - HostName = "K8S_HostName" - SrcHostName = Src + HostName - DstHostName = Dst + HostName - Zone = "K8S_Zone" - SrcZone = Src + Zone - DstZone = Dst + Zone - Cluster = "K8S_ClusterName" - Layer = "K8S_FlowLayer" - Packets = "Packets" - PktDropPackets = "PktDropPackets" - Proto = "Proto" - Bytes = "Bytes" - DSCP = "Dscp" - PktDropBytes = "PktDropBytes" - FlowDirection = "FlowDirection" - Interfaces = "Interfaces" - IfDirections = "IfDirections" - DNSID = "DnsId" - DNSLatency = "DnsLatencyMs" - DNSErrNo = "DnsErrno" - DNSCode = "DnsFlagsResponseCode" - Duplicate = "Duplicate" - TimeFlowRTT = "TimeFlowRttNs" + Src = "Src" + Dst = "Dst" + Namespace = "K8S_Namespace" + SrcNamespace = Src + Namespace + DstNamespace = Dst + Namespace + OwnerType = "K8S_OwnerType" + SrcOwnerType = Src + OwnerType + DstOwnerType = Dst + OwnerType + OwnerName = "K8S_OwnerName" + SrcOwnerName = Src + OwnerName + DstOwnerName = Dst + OwnerName + Type = "K8S_Type" + SrcType = Src + Type + DstType = Dst + Type + Name = "K8S_Name" + SrcName = Src + Name + DstName = Dst + Name + Addr = "Addr" + SrcAddr = Src + Addr + DstAddr = Dst + Addr + Port = "Port" + SrcPort = Src + Port + DstPort = Dst + Port + HostIP = "K8S_HostIP" + SrcHostIP = Src + HostIP + DstHostIP = Dst + HostIP + HostName = "K8S_HostName" + SrcHostName = Src + HostName + DstHostName = Dst + HostName + Zone = "K8S_Zone" + SrcZone = Src + Zone + DstZone = Dst + Zone + Cluster = "K8S_ClusterName" + Layer = "K8S_FlowLayer" + Packets = "Packets" + Proto = "Proto" + Bytes = "Bytes" + DSCP = "Dscp" + PktDropPackets = "PktDropPackets" + PktDropBytes = "PktDropBytes" + PktDropLatestState = "PktDropLatestState" + PktDropLatestDropCause = "PktDropLatestDropCause" + FlowDirection = "FlowDirection" + Interfaces = "Interfaces" + IfDirections = "IfDirections" + DNSID = "DnsId" + DNSLatency = "DnsLatencyMs" + DNSErrNo = "DnsErrno" + DNSCode = "DnsFlagsResponseCode" + Duplicate = "Duplicate" + TimeFlowRTT = "TimeFlowRttNs" ) func IsNumeric(v string) bool { diff --git a/pkg/prometheus/inventory.go b/pkg/prometheus/inventory.go index a9f4cec4d..3d5c27a2c 100644 --- a/pkg/prometheus/inventory.go +++ b/pkg/prometheus/inventory.go @@ -76,6 +76,16 @@ func (i *Inventory) Search(neededLabels []string, valueField string) SearchResul func (i *Inventory) searchWithDir(neededLabels []string, valueField string, dir config.FlowDirection) SearchResult { sr := SearchResult{} + // Special case, when the query has a filter to PktDropState/Cause and value field is bytes/packets, + // we must consider value field is actually PktDropBytes/Packets + if slices.Contains(neededLabels, fields.PktDropLatestDropCause) || slices.Contains(neededLabels, fields.PktDropLatestState) { + switch valueField { + case fields.Bytes: + valueField = fields.PktDropBytes + case fields.Packets: + valueField = fields.PktDropPackets + } + } for _, m := range i.metrics { match, missingLabels := checkMatch(&m, neededLabels, valueField, dir) if match { @@ -84,12 +94,12 @@ func (i *Inventory) searchWithDir(neededLabels []string, valueField string, dir return sr } sr.Candidates = append(sr.Candidates, m.Name) - } else if m.Enabled && (sr.MissingLabels == nil || len(missingLabels) < len(sr.MissingLabels)) { + } else if m.Enabled && len(missingLabels) > 0 && (sr.MissingLabels == nil || len(missingLabels) < len(sr.MissingLabels)) { // Keep smaller possible set of missing labels sr.MissingLabels = missingLabels } } - log.Debugf("No metric match for %v / %s (/ %s)", neededLabels, valueField, dir) + log.Debugf("No metric match for %v / %s / %s", neededLabels, valueField, dir) return sr } diff --git a/pkg/prometheus/inventory_test.go b/pkg/prometheus/inventory_test.go index 2072502b1..e9cd10627 100644 --- a/pkg/prometheus/inventory_test.go +++ b/pkg/prometheus/inventory_test.go @@ -98,3 +98,9 @@ func TestInventory_Search_RTT_Candidate(t *testing.T) { search := inv.Search([]string{"SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "DstK8S_Type", "SrcK8S_Type"}, "TimeFlowRttNs") assert.Equal(t, []string{"netobserv_workload_rtt_seconds"}, search.Candidates) } + +func TestInventory_Search_MissingLabels(t *testing.T) { + inv := NewInventory(&config.Prometheus{Metrics: configuredMetrics}) + search := inv.Search([]string{"SrcK8S_Namespace", "DstK8S_Namespace", "SrcK8S_HostName"}, "Bytes") + assert.Equal(t, []string{"SrcK8S_HostName"}, search.MissingLabels) +} diff --git a/web/locales/en/plugin__netobserv-plugin.json b/web/locales/en/plugin__netobserv-plugin.json index c2bad9282..04eb294f3 100644 --- a/web/locales/en/plugin__netobserv-plugin.json +++ b/web/locales/en/plugin__netobserv-plugin.json @@ -168,8 +168,8 @@ "Configuration limits": "Configuration limits", "Metrics": "Metrics", "You may consider the following changes to avoid this error:": "You may consider the following changes to avoid this error:", - "Add missing metrics to prometheus using FlowMetric API": "Add missing metrics to prometheus using FlowMetric API", - "Enable Loki in FlowCollector API": "Enable Loki in FlowCollector API", + "Add missing metrics to prometheus in the FlowCollector API (processor.metrics.includeList)": "Add missing metrics to prometheus in the FlowCollector API (processor.metrics.includeList)", + "Enable Loki in the FlowCollector API (loki.enable)": "Enable Loki in the FlowCollector API (loki.enable)", "Reduce the Query Options -> limit to reduce the number of results": "Reduce the Query Options -> limit to reduce the number of results", "Increase Loki \"max_entries_limit_per_query\" entry in configuration file": "Increase Loki \"max_entries_limit_per_query\" entry in configuration file", "Add Namespace, Owner or Resource filters (which use indexed fields) to improve the query performance": "Add Namespace, Owner or Resource filters (which use indexed fields) to improve the query performance", @@ -318,6 +318,7 @@ "When in \"Match any\" mode, try using only Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance": "When in \"Match any\" mode, try using only Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance", "Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance": "Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance", "Add more filters or decrease limit / range to improve the query performance": "Add more filters or decrease limit / range to improve the query performance", + "Could not fetch drop information": "Could not fetch drop information", "Overview": "Overview", "Traffic flows": "Traffic flows", "Topology": "Topology", diff --git a/web/src/components/messages/error.tsx b/web/src/components/messages/error.tsx index 5391319ef..6bf704538 100644 --- a/web/src/components/messages/error.tsx +++ b/web/src/components/messages/error.tsx @@ -132,9 +132,11 @@ export const Error: React.FC = ({ title, error, isLokiRelated }) => {error.includes('promUnsupported') && ( <> - {t('Add missing metrics to prometheus using FlowMetric API')} + {t('Add missing metrics to prometheus in the FlowCollector API (processor.metrics.includeList)')} + + + {t('Enable Loki in the FlowCollector API (loki.enable)')} - {t('Enable Loki in FlowCollector API')} )} {error.includes('max entries limit') && ( diff --git a/web/src/components/netflow-traffic.tsx b/web/src/components/netflow-traffic.tsx index 839a8f240..ce7fba1e1 100644 --- a/web/src/components/netflow-traffic.tsx +++ b/web/src/components/netflow-traffic.tsx @@ -76,13 +76,14 @@ import { TopologyGroupTypes, TopologyOptions } from '../model/topology'; +import { Warning } from '../model/warnings'; import { getFetchFunctions as getBackAndForthFetch } from '../utils/back-and-forth'; import { Column, ColumnsId, ColumnSizeMap, getDefaultColumns } from '../utils/columns'; import { loadConfig } from '../utils/config'; import { ContextSingleton } from '../utils/context'; import { computeStepInterval, getTimeRangeOptions, TimeRange } from '../utils/datetime'; import { formatDuration, getDateMsInSeconds, getDateSInMiliseconds, parseDuration } from '../utils/duration'; -import { getHTTPErrorDetails, isPromUnsupportedError } from '../utils/errors'; +import { getHTTPErrorDetails, getPromUnsupportedError, isPromUnsupportedError } from '../utils/errors'; import { exportToPng } from '../utils/export'; import { checkFilterAvailable, getFilterDefinitions } from '../utils/filter-definitions'; import { mergeFlowReporters } from '../utils/flows'; @@ -199,7 +200,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i } const [config, setConfig] = React.useState(defaultConfig); - const [warningMessage, setWarningMessage] = React.useState(); + const [warning, setWarning] = React.useState(); const [showViewOptions, setShowViewOptions] = useLocalStorage(localStorageShowOptionsKey, false); const [showHistogram, setShowHistogram] = useLocalStorage(localStorageShowHistogramKey, false); const [isViewOptionOverflowMenuOpen, setViewOptionOverflowMenuOpen] = React.useState(false); @@ -472,7 +473,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i setFilters(f); setFlows([]); setMetrics(defaultNetflowMetrics); - setWarningMessage(undefined); + setWarning(undefined); }, [setFilters, setFlows] ); @@ -611,12 +612,12 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i (query: Promise) => { setLastRefresh(undefined); setLastDuration(undefined); - setWarningMessage(undefined); + setWarning(undefined); Promise.race([query, new Promise((resolve, reject) => setTimeout(reject, 4000, 'slow'))]).then( null, (reason: string) => { if (reason === 'slow') { - setWarningMessage(`${t('Query is slow')}`); + setWarning({ type: 'slow', summary: `${t('Query is slow')}` }); } } ); @@ -626,22 +627,30 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i [] ); - const slownessReason = React.useCallback((): string => { - if (match === 'any' && hasNonIndexFields(filters.list)) { - return t( - // eslint-disable-next-line max-len - 'When in "Match any" mode, try using only Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance' - ); - } - if (match === 'all' && !hasIndexFields(filters.list)) { - return t( - // eslint-disable-next-line max-len - 'Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance' - ); - } - return t('Add more filters or decrease limit / range to improve the query performance'); + const checkSlownessReason = React.useCallback( + (w: Warning | undefined): Warning | undefined => { + if (w?.type == 'slow') { + let reason = ''; + if (match === 'any' && hasNonIndexFields(filters.list)) { + reason = t( + // eslint-disable-next-line max-len + 'When in "Match any" mode, try using only Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance' + ); + } else if (match === 'all' && !hasIndexFields(filters.list)) { + reason = t( + // eslint-disable-next-line max-len + 'Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance' + ); + } else { + reason = t('Add more filters or decrease limit / range to improve the query performance'); + } + return { ...w, details: reason }; + } + return w; + }, // eslint-disable-next-line react-hooks/exhaustive-deps - }, [match, filters]); + [match, filters] + ); const fetchTable = React.useCallback( (fq: FlowQuery) => { @@ -1005,13 +1014,24 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i if (droppedType) { promises.push( - getMetrics({ ...fq, type: droppedType }, range).then(res => { - const droppedRateMetrics = {} as RateMetrics; - droppedRateMetrics[getRateMetricKey(topologyMetricType)] = res.metrics; - currentMetrics = { ...currentMetrics, droppedRateMetrics }; - setMetrics(currentMetrics); - return res.stats; - }) + getMetrics({ ...fq, type: droppedType }, range) + .then(res => { + const droppedRateMetrics = {} as RateMetrics; + droppedRateMetrics[getRateMetricKey(topologyMetricType)] = res.metrics; + currentMetrics = { ...currentMetrics, droppedRateMetrics }; + setMetrics(currentMetrics); + return res.stats; + }) + .catch(err => { + // Error might occur for instance when fetching node-based topology with drop feature enabled, and Loki disabled + // We don't want to break the whole topology due to missing drops enrichement + let strErr = getHTTPErrorDetails(err, true); + if (isPromUnsupportedError(strErr)) { + strErr = getPromUnsupportedError(strErr); + } + setWarning({ type: 'cantfetchdrops', summary: t('Could not fetch drop information'), details: strErr }); + return { numQueries: 0, dataSources: [], limitReached: false }; + }) ); } else if (!['PktDropBytes', 'PktDropPackets'].includes(topologyMetricType)) { currentMetrics = { ...currentMetrics, droppedRateMetrics: undefined }; @@ -1019,7 +1039,9 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i } return Promise.all(promises); }, - [config.features, getFetchFunctions, topologyMetricType, topologyMetricFunction, range] + // "t" dependency kills jest + // eslint-disable-next-line react-hooks/exhaustive-deps + [config.features, getFetchFunctions, topologyMetricType, topologyMetricFunction, range, setWarning] ); const tick = React.useCallback(() => { @@ -1076,7 +1098,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i setFlows([]); setMetrics(defaultNetflowMetrics); setError(getHTTPErrorDetails(err, true)); - setWarningMessage(undefined); + setWarning(undefined); }) .finally(() => { const endDate = new Date(); @@ -1536,8 +1558,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i limit={limit} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason()} + warning={checkSlownessReason(warning)} range={range} showDNSLatency={isDNSTracking()} showRTTLatency={isFlowRTT()} @@ -1685,8 +1706,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i loading={loading} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason()} + warning={checkSlownessReason(warning)} isShowQuerySummary={isShowQuerySummary} toggleQuerySummary={() => onToggleQuerySummary(!isShowQuerySummary)} isDark={isDarkTheme} @@ -1698,8 +1718,7 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i loading={loading} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason()} + warning={checkSlownessReason(warning)} range={range} type={recordType} isShowQuerySummary={isShowQuerySummary} @@ -1749,13 +1768,13 @@ export const NetflowTraffic: React.FC = ({ forcedFilters, i setOverviewFocus, setTopologyOptions, size, - slownessReason, + checkSlownessReason, stats, t, topologyMetricFunction, topologyMetricType, topologyOptions, - warningMessage + warning ]); //update data on filters changes diff --git a/web/src/components/query-summary/flows-query-summary-content.tsx b/web/src/components/query-summary/flows-query-summary-content.tsx index 8d7ef90b9..ee3912e30 100644 --- a/web/src/components/query-summary/flows-query-summary-content.tsx +++ b/web/src/components/query-summary/flows-query-summary-content.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { Record } from '../../api/ipfix'; import { RecordType } from '../../model/flow-query'; +import { Warning } from '../../model/warnings'; import { rangeToSeconds, TimeRange } from '../../utils/datetime'; import { valueFormat } from '../../utils/format'; import StatsQuerySummary from './stats-query-summary'; @@ -18,8 +19,7 @@ export interface FlowsQuerySummaryContentProps { loading?: boolean; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; direction: 'row' | 'column'; className?: string; isShowQuerySummary?: boolean; @@ -35,8 +35,7 @@ export const FlowsQuerySummaryContent: React.FC = loading, lastRefresh, lastDuration, - warningMessage, - slownessReason, + warning, direction, className, isShowQuerySummary, @@ -105,8 +104,7 @@ export const FlowsQuerySummaryContent: React.FC = lastRefresh={lastRefresh} lastDuration={lastDuration} numQueries={numQueries} - warningMessage={warningMessage} - slownessReason={slownessReason} + warning={warning} /> {!_.isEmpty(flows) && ( diff --git a/web/src/components/query-summary/flows-query-summary.tsx b/web/src/components/query-summary/flows-query-summary.tsx index 0c8cb6b08..1b3c734df 100644 --- a/web/src/components/query-summary/flows-query-summary.tsx +++ b/web/src/components/query-summary/flows-query-summary.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import { Record } from '../../api/ipfix'; import { Stats } from '../../api/loki'; import { RecordType } from '../../model/flow-query'; +import { Warning } from '../../model/warnings'; import { TimeRange } from '../../utils/datetime'; import { FlowsQuerySummaryContent } from './flows-query-summary-content'; import './query-summary.css'; @@ -16,8 +17,7 @@ export interface FlowQuerySummaryProps { loading?: boolean; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; isShowQuerySummary?: boolean; toggleQuerySummary?: () => void; } @@ -30,8 +30,7 @@ export const FlowsQuerySummary: React.FC = ({ loading, lastRefresh, lastDuration, - warningMessage, - slownessReason, + warning, isShowQuerySummary, toggleQuerySummary }) => { @@ -48,8 +47,7 @@ export const FlowsQuerySummary: React.FC = ({ loading={loading} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason} + warning={warning} isShowQuerySummary={isShowQuerySummary} toggleQuerySummary={toggleQuerySummary} /> diff --git a/web/src/components/query-summary/metrics-query-summary-content.tsx b/web/src/components/query-summary/metrics-query-summary-content.tsx index b2f22446e..cd1a3beb0 100644 --- a/web/src/components/query-summary/metrics-query-summary-content.tsx +++ b/web/src/components/query-summary/metrics-query-summary-content.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { getRateMetricKey, NetflowMetrics } from '../../api/loki'; import { MetricType } from '../../model/flow-query'; +import { Warning } from '../../model/warnings'; import { valueFormat } from '../../utils/format'; import StatsQuerySummary from './stats-query-summary'; @@ -24,8 +25,7 @@ export interface MetricsQuerySummaryContentProps { loading?: boolean; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; direction: 'row' | 'column'; className?: string; isShowQuerySummary?: boolean; @@ -40,8 +40,7 @@ export const MetricsQuerySummaryContent: React.FC {metricsToShow()} diff --git a/web/src/components/query-summary/metrics-query-summary.tsx b/web/src/components/query-summary/metrics-query-summary.tsx index d2fa1750d..a94973b3b 100644 --- a/web/src/components/query-summary/metrics-query-summary.tsx +++ b/web/src/components/query-summary/metrics-query-summary.tsx @@ -1,6 +1,7 @@ import { Card } from '@patternfly/react-core'; import * as React from 'react'; import { NetflowMetrics, Stats } from '../../api/loki'; +import { Warning } from '../../model/warnings'; import { MetricsQuerySummaryContent } from './metrics-query-summary-content'; import './query-summary.css'; @@ -10,8 +11,7 @@ export interface MetricsQuerySummaryProps { loading?: boolean; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; isShowQuerySummary?: boolean; toggleQuerySummary?: () => void; isDark?: boolean; @@ -23,8 +23,7 @@ export const MetricsQuerySummary: React.FC = ({ loading, lastRefresh, lastDuration, - warningMessage, - slownessReason, + warning, isShowQuerySummary, toggleQuerySummary, isDark @@ -39,8 +38,7 @@ export const MetricsQuerySummary: React.FC = ({ loading={loading} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason} + warning={warning} isShowQuerySummary={isShowQuerySummary} toggleQuerySummary={toggleQuerySummary} isDark={isDark} diff --git a/web/src/components/query-summary/stats-query-summary.tsx b/web/src/components/query-summary/stats-query-summary.tsx index 813a20ff7..6f242f9d2 100644 --- a/web/src/components/query-summary/stats-query-summary.tsx +++ b/web/src/components/query-summary/stats-query-summary.tsx @@ -2,6 +2,7 @@ import { FlexItem, Text, TextVariants, Tooltip } from '@patternfly/react-core'; import { ExclamationTriangleIcon, GlobeAmericasIcon } from '@patternfly/react-icons'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; +import { Warning } from '../../model/warnings'; import { formatDurationAboveMillisecond } from '../../utils/duration'; import './query-summary.css'; @@ -10,8 +11,7 @@ export interface StatsQuerySummaryProps { loading?: boolean; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; numQueries?: number; dataSources?: string[]; } @@ -23,8 +23,7 @@ export const StatsQuerySummary: React.FC = ({ lastRefresh, lastDuration, loading, - warningMessage, - slownessReason + warning }) => { const { t } = useTranslation('plugin__netobserv-plugin'); @@ -50,18 +49,18 @@ export const StatsQuerySummary: React.FC = ({ {dataSources?.length && {t('Datasource(s): {{sources}}', { sources: formatDatasources() })}} {numQueries && {t('Query count: {{count}}', { count: numQueries })}} {durationText !== '' && {t('Duration: {{duration}}', { duration: durationText })}} - {warningMessage !== undefined && ( + {warning !== undefined && ( <>
- {warningMessage} - {slownessReason} + {warning.summary} + {warning.details} )} } >
- {warningMessage !== undefined ? : } + {warning !== undefined ? : } {dateText} {detailed && numQueries && ` ${t('running')} ${numQueries} ${numQueries > 1 ? t('queries') : t('query')}`} diff --git a/web/src/components/query-summary/summary-panel-content.tsx b/web/src/components/query-summary/summary-panel-content.tsx index aa91097d2..c5b040d8b 100644 --- a/web/src/components/query-summary/summary-panel-content.tsx +++ b/web/src/components/query-summary/summary-panel-content.tsx @@ -15,6 +15,7 @@ import { useTranslation } from 'react-i18next'; import { Record } from '../../api/ipfix'; import { NetflowMetrics, Stats } from '../../api/loki'; import { RecordType } from '../../model/flow-query'; +import { Warning } from '../../model/warnings'; import { compareStrings } from '../../utils/base-compare'; import { config } from '../../utils/config'; import { TimeRange } from '../../utils/datetime'; @@ -45,8 +46,7 @@ export interface SummaryPanelContentProps { range: number | TimeRange; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; showDNSLatency?: boolean; showRTTLatency?: boolean; } @@ -61,8 +61,7 @@ export const SummaryPanelContent: React.FC = ({ range, lastRefresh, lastDuration, - warningMessage, - slownessReason, + warning, showDNSLatency, showRTTLatency }) => { @@ -412,8 +411,7 @@ export const SummaryPanelContent: React.FC = ({ dataSources={stats?.dataSources} lastRefresh={lastRefresh} lastDuration={lastDuration} - slownessReason={slownessReason} - warningMessage={warningMessage} + warning={warning} /> ) : ( = ({ range={range} lastRefresh={lastRefresh} lastDuration={lastDuration} - slownessReason={slownessReason} - warningMessage={warningMessage} + warning={warning} /> )} diff --git a/web/src/components/query-summary/summary-panel.tsx b/web/src/components/query-summary/summary-panel.tsx index 586a6fcc8..6855ab989 100644 --- a/web/src/components/query-summary/summary-panel.tsx +++ b/web/src/components/query-summary/summary-panel.tsx @@ -12,6 +12,7 @@ import { useTranslation } from 'react-i18next'; import { Record } from '../../api/ipfix'; import { NetflowMetrics, Stats } from '../../api/loki'; import { RecordType } from '../../model/flow-query'; +import { Warning } from '../../model/warnings'; import { TimeRange } from '../../utils/datetime'; import { defaultSize, maxSize, minSize } from '../../utils/panel'; import { SummaryPanelContent } from './summary-panel-content'; @@ -28,8 +29,7 @@ export interface SummaryPanelProps { range: number | TimeRange; lastRefresh?: Date; lastDuration?: number; - warningMessage?: string; - slownessReason?: string; + warning?: Warning; showDNSLatency?: boolean; showRTTLatency?: boolean; id?: string; @@ -45,8 +45,7 @@ export const SummaryPanel: React.FC = ({ range, lastRefresh, lastDuration, - warningMessage, - slownessReason, + warning, showDNSLatency, showRTTLatency, id, @@ -80,8 +79,7 @@ export const SummaryPanel: React.FC = ({ range={range} lastRefresh={lastRefresh} lastDuration={lastDuration} - warningMessage={warningMessage} - slownessReason={slownessReason} + warning={warning} showDNSLatency={showDNSLatency} showRTTLatency={showRTTLatency} /> diff --git a/web/src/model/warnings.ts b/web/src/model/warnings.ts new file mode 100644 index 000000000..7abb8815e --- /dev/null +++ b/web/src/model/warnings.ts @@ -0,0 +1,7 @@ +export type WarningType = 'slow' | 'cantfetchdrops'; + +export interface Warning { + summary: string; + details?: string; + type: WarningType; +}