fix: use triggers.length for incident alert count and sort Related Alerts

- Replace alert_count with triggers.length for accurate count display
- Rename 'Total Triggers' to 'Total Alerts' for consistency
- Show all unique alerts in Related Alerts (was showing only 2 from topology_context.nodes)
- Sort Related Alerts by trigger count (descending order)
This commit is contained in:
ByteBaker
2026-01-30 14:16:28 +05:30
parent 25c9e4a06e
commit 50e45e2ea7
2 changed files with 25 additions and 13 deletions
@@ -109,10 +109,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
>
<div class="tw:flex tw:items-center tw:gap-1.5">
<q-icon name="notifications_active" size="14px" />
<span>{{ incidentDetails.alert_count }} Alerts</span>
<span>{{ triggers.length }} Alerts</span>
</div>
<q-tooltip :delay="200" class="tw:text-sm">
{{ t("alerts.incidents.alertCount") }}: {{ incidentDetails.alert_count }} correlated alerts
{{ t("alerts.incidents.alertCount") }}: {{ triggers.length }} correlated alerts
</q-tooltip>
</q-badge>
</div>
@@ -272,14 +272,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div v-if="activeTab === 'overview'" class="tw:flex tw:flex-col tw:flex-1 tw:overflow-hidden">
<!-- SECTION 1: Hero Metrics (100px height) -->
<div class="tw:flex tw:gap-3 tw:mb-3" style="height: 100px;">
<!-- 1. Total Triggers Card -->
<!-- 1. Total Alerts Card -->
<div
class="tw:flex-1 tw:flex tw:flex-col tw:justify-between el-border el-border-radius o2-incident-card-bg tw:transition-all tw:duration-200 tw:cursor-pointer tw:p-3"
>
<!-- Top: Title and Icon -->
<div class="tw:flex tw:justify-between tw:items-start">
<div :class="store.state.theme === 'dark' ? 'tw:text-gray-300' : 'tw:text-gray-700'" class="tw:text-sm tw:font-medium">
Total Triggers
Total Alerts
</div>
<div class="tw:w-8 tw:h-8 tw:rounded-lg tw:flex tw:items-center tw:justify-center" :class="store.state.theme === 'dark' ? 'tw:bg-amber-500/10' : 'tw:bg-amber-50'">
<q-icon name="bolt" :class="store.state.theme === 'dark' ? 'tw:text-amber-400' : 'tw:text-amber-600'" style="font-size: 20px;" />
@@ -767,7 +767,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<!-- 2.2C: Alert Flow Panel (25% of available height after gaps) - Conditional -->
<div
v-if="incidentDetails?.topology_context?.nodes?.length"
v-if="sortedAlertsByTriggerCount?.length"
class="el-border el-border-radius o2-incident-card-bg tw:flex tw:flex-col tw:overflow-hidden"
:style="{
height: 'calc(25% - 4px)'
@@ -787,13 +787,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div class="tw:px-3 tw:pb-3 tw:overflow-y-auto tw:flex-1" style="min-height: 0;">
<div class="tw:flex tw:flex-col tw:gap-0">
<div
v-for="(node, index) in incidentDetails.topology_context.nodes"
:key="node.alert_id"
v-for="(alert, index) in sortedAlertsByTriggerCount"
:key="alert.id"
class="tw:py-2.5 tw:border-b"
:style="{
borderColor: store.state.theme === 'dark' ? '#444444' : '#E7EAEE'
}"
:class="{ 'tw:border-b-0': index === incidentDetails.topology_context.nodes.length - 1 }"
:class="{ 'tw:border-b-0': index === sortedAlertsByTriggerCount.length - 1 }"
>
<div
:class="store.state.theme === 'dark' ? 'tw:text-gray-200' : 'tw:text-gray-900'"
@@ -806,18 +806,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{{ index + 1 }}.
</span>
<div class="tw:flex-1 tw:min-w-0">
<q-tooltip v-if="node.alert_name.length > 30">
{{ node.alert_name }}
<q-tooltip v-if="alert.name.length > 30">
{{ alert.name }}
</q-tooltip>
<span class="tw:font-medium tw:truncate tw:block">
{{ node.alert_name.length > 30 ? node.alert_name.substring(0, 30) + '...' : node.alert_name }}
{{ alert.name.length > 30 ? alert.name.substring(0, 30) + '...' : alert.name }}
</span>
</div>
<div class="tw:flex-shrink-0" style="width: 120px;">
<span
:class="store.state.theme === 'dark' ? 'tw:text-gray-400' : 'tw:text-gray-600'"
>
Fired {{ getTriggerCountForAlert(node.alert_id) }} time(s)
Fired {{ getTriggerCountForAlert(alert.id) }} time(s)
</span>
</div>
</div>
@@ -1402,6 +1402,16 @@ export default defineComponent({
return triggers.value.filter(t => t.alert_id === alertId).length;
};
// Computed: Alerts sorted by trigger count (descending)
const sortedAlertsByTriggerCount = computed(() => {
if (!alerts.value || alerts.value.length === 0) return [];
return [...alerts.value].sort((a, b) => {
const countA = getTriggerCountForAlert(a.id);
const countB = getTriggerCountForAlert(b.id);
return countB - countA; // Descending order
});
});
// Peak Alert Rate - find the highest concentration of alerts
const peakAlertRate = computed(() => {
if (!incidentDetails.value || triggers.value.length === 0) return "N/A";
@@ -2539,6 +2549,7 @@ export default defineComponent({
affectedServicesCount,
alertFrequency,
getTriggerCountForAlert,
sortedAlertsByTriggerCount,
peakAlertRate,
peakActivity,
correlationType,
+2 -1
View File
@@ -260,7 +260,8 @@ export const convertServiceGraphToTree = (
// Root node: sum of all outgoing edges (traffic flowing from this node)
totalRequests = outgoingEdges.reduce((sum: number, edge: any) => sum + (edge.total_requests ?? 0), 0);
failedRequests = outgoingEdges.reduce((sum: number, edge: any) => sum + (edge.failed_requests ?? 0), 0);
errorRate = totalRequests > 0 ? (failedRequests / totalRequests) * 100 : 0;
// If no outgoing edges, fall back to node's own error_rate
errorRate = totalRequests > 0 ? (failedRequests / totalRequests) * 100 : (node.error_rate ?? 0);
}
// Calculate connections count (incoming + outgoing edges)