feat(traffic): показать аналитику IPFIX по серверам и интерфейсам
Docker images / prepare-release (push) Successful in 12s
Docker images / backend-image (push) Successful in 2m10s
Docker images / frontend-image (push) Successful in 2m53s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 48s
Docker images / publish-release (push) Successful in 11s
Docker images / prepare-release (push) Successful in 12s
Docker images / backend-image (push) Successful in 2m10s
Docker images / frontend-image (push) Successful in 2m53s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 48s
Docker images / publish-release (push) Successful in 11s
Резолвить ifIndex в имена RouterOS, дать вкладке Потоки ту же оболочку сервер/клиент/iface, что у обычного трафика, и обновлять срезы live без перезагрузки. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+24
-1
@@ -158,7 +158,7 @@ CREATE TABLE IF NOT EXISTS flow_buckets (
|
||||
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_flow_buckets_unique
|
||||
ON flow_buckets(server_id, bucket_at, src, dst, proto, src_port, dst_port);
|
||||
ON flow_buckets(server_id, bucket_at, src, dst, proto, src_port, dst_port, in_iface);
|
||||
CREATE INDEX IF NOT EXISTS idx_flow_buckets_server_time
|
||||
ON flow_buckets(server_id, bucket_at);
|
||||
|
||||
@@ -805,6 +805,29 @@ SELECT 1, 'https://acme-v02.api.letsencrypt.org/directory', '', '', ''
|
||||
WHERE NOT EXISTS (SELECT 1 FROM acme_settings WHERE id = 1);
|
||||
`)
|
||||
|
||||
{
|
||||
const flowIndexes = sqlite.prepare(`PRAGMA index_list('flow_buckets')`).all() as Array<{
|
||||
name?: string
|
||||
unique?: number
|
||||
}>
|
||||
let hasIfaceUnique = false
|
||||
for (const idx of flowIndexes) {
|
||||
if (!idx.name || !idx.unique) continue
|
||||
const info = sqlite.prepare(`PRAGMA index_info(${JSON.stringify(idx.name)})`).all() as Array<{ name?: string }>
|
||||
const names = info.map((c) => c.name)
|
||||
if (names.includes("in_iface") && names.includes("src") && names.includes("dst")) {
|
||||
hasIfaceUnique = true
|
||||
}
|
||||
}
|
||||
if (!hasIfaceUnique) {
|
||||
sqlite.exec(`DROP INDEX IF EXISTS idx_flow_buckets_unique`)
|
||||
sqlite.exec(`
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_flow_buckets_unique
|
||||
ON flow_buckets(server_id, bucket_at, src, dst, proto, src_port, dst_port, in_iface)
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
const certIssueJobCols = sqlite.prepare(`PRAGMA table_info('certificate_issue_jobs')`).all() as Array<{ name?: string }>
|
||||
if (!certIssueJobCols.some((c) => c.name === "source")) {
|
||||
sqlite.exec(`ALTER TABLE certificate_issue_jobs ADD COLUMN source TEXT NOT NULL DEFAULT 'manual'`)
|
||||
|
||||
@@ -198,7 +198,7 @@ export const flowBuckets = sqliteTable("flow_buckets", {
|
||||
inIface: text("in_iface").notNull().default(""),
|
||||
}, (t) => [
|
||||
uniqueIndex("idx_flow_buckets_unique").on(
|
||||
t.serverId, t.bucketAt, t.src, t.dst, t.proto, t.srcPort, t.dstPort,
|
||||
t.serverId, t.bucketAt, t.src, t.dst, t.proto, t.srcPort, t.dstPort, t.inIface,
|
||||
),
|
||||
])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user