Development
This commit is contained in:
parent
e9166d8a6a
commit
0983e14de4
7 changed files with 494 additions and 160 deletions
|
|
@ -99,5 +99,75 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
,
|
||||
{
|
||||
"type": "card",
|
||||
"label": "DNS Statistics",
|
||||
"items": [
|
||||
{
|
||||
"type": "grid",
|
||||
"rows": [
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Tracking Since"},
|
||||
{"type": "grid_value", "text": "%DNS_METRICS_SINCE%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Last Updated"},
|
||||
{"type": "grid_value", "text": "%DNS_METRICS_UPDATED%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Total Queries"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_QUERIES%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Hits"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_HITS% (%DNS_STAT_HIT_RATE% hit rate)"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Forwarded to Upstream"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_FORWARDED%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Authoritative Answers"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_AUTH%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "TCP Peak"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_TCP_PEAK%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Capacity"},
|
||||
{"type": "grid_value", "text": "%DNS_CACHE_SIZE% entries"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Evictions"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_CACHE_EVICTIONS%"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "raw_html",
|
||||
"html": "%DNS_PROVIDERS_TABLE%"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,12 +1,25 @@
|
|||
import json
|
||||
import config_utils
|
||||
from pages.overview.view import load_dns_metrics, _dns_providers_table
|
||||
|
||||
|
||||
def collect_tokens(cfg):
|
||||
tokens = config_utils.collect_layout_tokens(cfg)
|
||||
dns = cfg.get('upstream_dns', {})
|
||||
dns = cfg.get('upstream_dns', {})
|
||||
servers = dns.get('upstream_servers', [])
|
||||
tokens['DNS_STRICT_ORDER'] = 'true' if dns.get('strict_order') else 'false'
|
||||
tokens['DNS_CACHE_SIZE'] = str(dns.get('cache_size', '-'))
|
||||
tokens['DNS_STRICT_ORDER'] = 'true' if dns.get('strict_order') else 'false'
|
||||
tokens['DNS_CACHE_SIZE'] = str(dns.get('cache_size', '-'))
|
||||
tokens['DNS_UPSTREAM_SERVERS_JSON'] = json.dumps(servers)
|
||||
|
||||
dns_stats = load_dns_metrics()
|
||||
tokens['DNS_METRICS_SINCE'] = dns_stats['since']
|
||||
tokens['DNS_METRICS_UPDATED'] = dns_stats['updated']
|
||||
tokens['DNS_STAT_QUERIES'] = dns_stats['queries']
|
||||
tokens['DNS_STAT_HITS'] = dns_stats['hits']
|
||||
tokens['DNS_STAT_HIT_RATE'] = dns_stats['hit_rate']
|
||||
tokens['DNS_STAT_FORWARDED'] = dns_stats['forwarded']
|
||||
tokens['DNS_STAT_AUTH'] = dns_stats['auth']
|
||||
tokens['DNS_STAT_TCP_PEAK'] = dns_stats['tcp_peak']
|
||||
tokens['DNS_STAT_CACHE_EVICTIONS'] = dns_stats['cache_evictions']
|
||||
tokens['DNS_PROVIDERS_TABLE'] = _dns_providers_table(dns_stats['servers'])
|
||||
return tokens
|
||||
|
|
|
|||
|
|
@ -81,64 +81,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"label": "DNS Statistics",
|
||||
"client_requirement": "client_is_viewer+",
|
||||
"items": [
|
||||
{
|
||||
"type": "grid",
|
||||
"rows": [
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Tracking Since"},
|
||||
{"type": "grid_value", "text": "%DNS_METRICS_SINCE%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Last Updated"},
|
||||
{"type": "grid_value", "text": "%DNS_METRICS_UPDATED%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Total Queries"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_QUERIES%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Hits"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_HITS% (%DNS_STAT_HIT_RATE% hit rate)"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Forwarded to Upstream"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_FORWARDED%"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Capacity"},
|
||||
{"type": "grid_value", "text": "%DNS_CACHE_SIZE% entries"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{"type": "grid_label", "text": "Cache Evictions"},
|
||||
{"type": "grid_value", "text": "%DNS_STAT_CACHE_EVICTIONS%"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "raw_html",
|
||||
"html": "%DNS_PROVIDERS_TABLE%"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"label": "Blocked Domains",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import json
|
||||
import os
|
||||
import threading
|
||||
from datetime import datetime
|
||||
import config_utils
|
||||
import factory
|
||||
import mod_dns_queries
|
||||
from pages.ddns.view import public_ip_info
|
||||
from pages.dhcpleases.view import live_dhcp_leases
|
||||
|
||||
METRICS_FILE = f'{config_utils.CONFIGS_DIR}/.dns-metrics'
|
||||
METRICS_DB = f'{config_utils.CONFIGS_DIR}/.dns-metrics2'
|
||||
|
||||
|
||||
def _fmt_since(since_str):
|
||||
|
|
@ -62,28 +64,69 @@ def _dns_providers_table(servers):
|
|||
|
||||
|
||||
def load_dns_metrics():
|
||||
empty = {'queries': '-', 'hits': '-', 'hit_rate': '-', 'forwarded': '-',
|
||||
'tcp_peak': '-', 'cache_evictions': '-', 'updated': '-', 'since': '-', 'servers': []}
|
||||
import sqlite3
|
||||
empty = {
|
||||
'queries': '-', 'hits': '-', 'hit_rate': '-', 'forwarded': '-',
|
||||
'auth': '-', 'tcp_peak': '-', 'cache_evictions': '-',
|
||||
'updated': '-', 'since': '-', 'servers': [],
|
||||
}
|
||||
try:
|
||||
with open(METRICS_FILE) as f:
|
||||
data = json.load(f)
|
||||
t = data.get('totals', {})
|
||||
meta = data.get('metadata', {})
|
||||
fwd = t.get('queries_forwarded', 0)
|
||||
hits = t.get('queries_answered_locally', 0)
|
||||
con = sqlite3.connect(METRICS_DB, timeout=5)
|
||||
con.execute('PRAGMA journal_mode=WAL')
|
||||
row = con.execute('''
|
||||
SELECT
|
||||
MIN(date), MAX(date),
|
||||
SUM(queries_forwarded), SUM(queries_answered_locally),
|
||||
SUM(queries_authoritative), SUM(cache_reused), MAX(tcp_hwm)
|
||||
FROM daily_totals
|
||||
''').fetchone()
|
||||
srv_rows = con.execute('''
|
||||
SELECT
|
||||
ds.address,
|
||||
SUM(ds.queries_sent),
|
||||
SUM(ds.retried),
|
||||
SUM(ds.failed),
|
||||
SUM(ds.nxdomain),
|
||||
(SELECT avg_latency_ms FROM daily_servers d2
|
||||
WHERE d2.address = ds.address AND d2.avg_latency_ms > 0
|
||||
ORDER BY d2.date DESC LIMIT 1)
|
||||
FROM daily_servers ds
|
||||
GROUP BY ds.address
|
||||
ORDER BY SUM(ds.queries_sent) DESC
|
||||
''').fetchall()
|
||||
con.close()
|
||||
|
||||
if not row or row[0] is None:
|
||||
return empty
|
||||
|
||||
since_raw, updated_raw, fwd, hits, auth, reused, tcp_hwm = row
|
||||
fwd = fwd or 0
|
||||
hits = hits or 0
|
||||
total = fwd + hits
|
||||
since_raw = meta.get('first_recorded', '-')
|
||||
updated_raw = meta.get('last_recorded', '-')
|
||||
|
||||
servers = [
|
||||
{
|
||||
'address': r[0],
|
||||
'queries_sent': r[1] or 0,
|
||||
'retried': r[2] or 0,
|
||||
'failed': r[3] or 0,
|
||||
'nxdomain': r[4] or 0,
|
||||
'avg_latency_ms': r[5] or 0,
|
||||
}
|
||||
for r in srv_rows
|
||||
]
|
||||
|
||||
return {
|
||||
'queries': f'{total:,}' if total else '-',
|
||||
'hits': f'{hits:,}' if hits else '-',
|
||||
'hit_rate': f'{hits / total * 100:.0f}%' if total > 0 else '-',
|
||||
'forwarded': f'{fwd:,}' if fwd else '-',
|
||||
'tcp_peak': str(t.get('tcp_hwm', 0)),
|
||||
'cache_evictions': f'{t.get("cache_reused", 0):,}',
|
||||
'auth': f'{(auth or 0):,}',
|
||||
'tcp_peak': str(tcp_hwm or 0),
|
||||
'cache_evictions': f'{(reused or 0):,}',
|
||||
'updated': _fmt_updated(updated_raw),
|
||||
'since': _fmt_since(since_raw),
|
||||
'servers': t.get('servers', []),
|
||||
'servers': servers,
|
||||
}
|
||||
except Exception:
|
||||
return empty
|
||||
|
|
@ -200,6 +243,9 @@ def bl_last_update():
|
|||
|
||||
|
||||
def collect_tokens(cfg):
|
||||
if has_query_logging(cfg):
|
||||
threading.Thread(target=mod_dns_queries.collect, args=(cfg,), daemon=True).start()
|
||||
|
||||
tokens = config_utils.collect_layout_tokens(cfg)
|
||||
non_vpn_vlans = [v for v in cfg.get('vlans', []) if not v.get('is_vpn')]
|
||||
dns = cfg.get('upstream_dns', {})
|
||||
|
|
@ -218,11 +264,8 @@ def collect_tokens(cfg):
|
|||
tokens['DNS_STAT_QUERIES'] = dns_stats['queries']
|
||||
tokens['DNS_STAT_HITS'] = dns_stats['hits']
|
||||
tokens['DNS_STAT_HIT_RATE'] = dns_stats['hit_rate']
|
||||
tokens['DNS_STAT_FORWARDED'] = dns_stats['forwarded']
|
||||
tokens['DNS_STAT_CACHE_EVICTIONS'] = dns_stats['cache_evictions']
|
||||
tokens['DNS_METRICS_UPDATED'] = dns_stats['updated']
|
||||
tokens['DNS_METRICS_SINCE'] = dns_stats['since']
|
||||
tokens['DNS_PROVIDERS_TABLE'] = _dns_providers_table(dns_stats['servers'])
|
||||
|
||||
tokens['STAT_BLOCKED_ALLTIME'] = all_time_blocked_display()
|
||||
tokens['HAS_QUERY_LOGGING'] = '1' if has_query_logging(cfg) else ''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue