feat(netflow): локальные GeoLite2-базы для стран и ASN потоков
Docker images / prepare-release (push) Successful in 13s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 4m31s
Docker images / updater-image (push) Successful in 48s
Docker images / backend-image (push) Successful in 3m1s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 15s
Docker images / prepare-release (push) Successful in 13s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 4m31s
Docker images / updater-image (push) Successful in 48s
Docker images / backend-image (push) Successful in 3m1s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 15s
Lookup страны/ASN при ingest теперь идёт сначала по локальным mmdb MaxMind GeoLite2 (Country + ASN, зеркало P3TERX, без ключей), с мгновенным синхронным ответом для IPv4/IPv6; RIPEstat остаётся fallback до первой загрузки баз и при промахе. - backend/src/services/traffic-flow-geoip.ts: ридеры maxmind, фасад resolveFlowIp (geoip-first → RIPE-кэш), статус ридеров - geoip-update-collector.ts: conditional GET по ETag, валидация пробоем 8.8.8.8 (US / AS15169), атомарная подмена с .prev-откатом - джоба планировщика geoip_update (по умолчанию раз в 7 дней), настройки geoip_settings + миграция 0004, API /api/geoip (GET/PUT/update), контракты @mmapp/contracts/geoip - engine/analytics/map-hops переведены на resolveFlowIp - секция «GeoIP-базы» в настройках NetFlow, метки джобы на странице сбора данных, тесты test:geoip
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
type InternetPathRunSnapshot,
|
||||
type CertificatesRenewRunSnapshot,
|
||||
type BackupsRunSnapshot,
|
||||
type GeoipUpdateRunSnapshot,
|
||||
type PingRunSnapshot,
|
||||
type ResourcesRunSnapshot,
|
||||
type SchedulerRunSnapshot,
|
||||
@@ -340,6 +341,41 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (snap.job === "geoip_update") {
|
||||
const g = snap as GeoipUpdateRunSnapshot
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{g.skipped ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: обновление уже выполнялось или задача отключена.</p>
|
||||
) : null}
|
||||
<dl className="grid grid-cols-2 gap-3 text-xs sm:grid-cols-4">
|
||||
<div>
|
||||
<dt className="text-muted-foreground">Баз проверено</dt>
|
||||
<dd className="font-mono font-medium">{g.checked}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-muted-foreground">Скачано</dt>
|
||||
<dd className="font-mono font-medium">{g.downloaded}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-muted-foreground">Без изменений</dt>
|
||||
<dd className="font-mono font-medium">{g.skippedUnchanged}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-muted-foreground">Объём, МБ</dt>
|
||||
<dd className="font-mono font-medium">{(g.bytes / 1024 / 1024).toFixed(1)}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{g.errors.length ? (
|
||||
<div className="rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-xs text-amber-800 dark:text-amber-200 flex flex-col gap-1">
|
||||
{g.errors.map((e, i) => (
|
||||
<p key={i} className="break-words">{e}</p>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (snap.job === "alert_engine") {
|
||||
const a = snap as AlertEngineRunSnapshot
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user