feat(api, web): enhance agent traffic statistics and update installation scripts
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 2m26s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped

- Improved the collection and reporting of agent traffic statistics, including total packets dropped and accepted, to provide a more comprehensive view of agent performance.
- Updated the `evofw-firewall.sh` script to capture and report traffic statistics before chain recreation, ensuring accurate data retention.
- Enhanced the installation script to support updates on already-installed agents, allowing for script and timer refresh without re-enrollment, while preserving existing credentials.
- Refactored UI components to utilize new traffic statistics, improving clarity and user experience in displaying agent performance metrics.

These changes enhance the overall functionality and usability of the agent management system, providing better insights and easier updates for users.
This commit is contained in:
Denozordec
2026-07-23 19:47:17 +07:00
parent 1b7d301153
commit 69e903aa1b
14 changed files with 293 additions and 140 deletions
@@ -3,6 +3,11 @@ import {
AgentPlatformIcon,
platformLabel,
} from '@/components/agents/agent-platform-icon'
import {
agentHasTrafficSample,
agentTrafficAccepted,
agentTrafficDropped,
} from '@/components/agents/agent-traffic'
import { StatusBadge } from '@/components/status-badge'
import { Badge } from '@/components/reui/badge'
import { Frame, FramePanel } from '@/components/reui/frame'
@@ -52,9 +57,9 @@ type AgentCardProps = {
}
export function AgentCard({ agent, selected, onSelect }: AgentCardProps) {
const hasApply = Boolean(agent.last_apply_at || agent.last_apply_status)
const dropped = formatPackets(agent.last_apply_packets_dropped, hasApply)
const accepted = formatPackets(agent.last_apply_packets_accepted, hasApply)
const hasApply = agentHasTrafficSample(agent)
const dropped = formatPackets(agentTrafficDropped(agent), hasApply)
const accepted = formatPackets(agentTrafficAccepted(agent), hasApply)
const traffic =
dropped === '—' && accepted === '—'
? '—'
@@ -24,6 +24,10 @@ import {
AgentPlatformIcon,
platformLabel,
} from '@/components/agents/agent-platform-icon'
import {
agentTrafficAccepted,
agentTrafficDropped,
} from '@/components/agents/agent-traffic'
import { AgentPolicySetsSortable } from '@/components/agents/agent-policy-sets-sortable'
import { AgentPolicyTrace } from '@/components/agents/agent-policy-trace'
import { AgentFactsPanel } from '@/components/agents/agent-facts-panel'
@@ -246,8 +250,8 @@ export function AgentDetailView({ agentId }: AgentDetailViewProps) {
icon: <ActivityIcon aria-hidden />,
iconClassName: 'text-warning',
label: 'Traffic',
description: `${a.last_apply_packets_dropped ?? 0} · ↑${a.last_apply_packets_accepted ?? 0}`,
hint: 'сумма counters',
description: `${agentTrafficDropped(a)} · ↑${agentTrafficAccepted(a)}`,
hint: 'накопительно',
variant: 'warning',
footer: (
<Button
@@ -15,6 +15,11 @@ import {
AgentPlatformIcon,
platformLabel,
} from '@/components/agents/agent-platform-icon'
import {
agentHasTrafficSample,
agentTrafficAccepted,
agentTrafficDropped,
} from '@/components/agents/agent-traffic'
import { Button } from '@evofw/ui/components/button'
import {
Tooltip,
@@ -217,22 +222,15 @@ export function AgentFleetDataGrid({
minSize: 110,
maxSize: 160,
accessorFn: (row) =>
(row.last_apply_packets_dropped ?? 0) +
(row.last_apply_packets_accepted ?? 0),
agentTrafficDropped(row) + agentTrafficAccepted(row),
header: ({ column }) => (
<DataGridColumnHeader column={column} title="Traffic" />
),
cell: ({ row }) => {
const a = row.original
const hasApply = Boolean(a.last_apply_at || a.last_apply_status)
const dropped = formatPackets(
a.last_apply_packets_dropped,
hasApply,
)
const accepted = formatPackets(
a.last_apply_packets_accepted,
hasApply,
)
const hasApply = agentHasTrafficSample(a)
const dropped = formatPackets(agentTrafficDropped(a), hasApply)
const accepted = formatPackets(agentTrafficAccepted(a), hasApply)
if (dropped === '—' && accepted === '—') {
return <DataGridMutedCell></DataGridMutedCell>
}
@@ -0,0 +1,19 @@
import type { Agent } from '@evofw/shared'
/** Cumulative Traffic counters (fallback to last apply snapshot). */
export function agentTrafficDropped(agent: Agent): number {
return agent.total_packets_dropped ?? agent.last_apply_packets_dropped ?? 0
}
export function agentTrafficAccepted(agent: Agent): number {
return agent.total_packets_accepted ?? agent.last_apply_packets_accepted ?? 0
}
export function agentHasTrafficSample(agent: Agent): boolean {
return Boolean(
agent.last_apply_at ||
agent.last_apply_status ||
(agent.total_packets_dropped ?? 0) > 0 ||
(agent.total_packets_accepted ?? 0) > 0,
)
}