mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-26 21:12:51 +08:00
💐 Sync 2026-09-01 02:40:52
This commit is contained in:
1 parent
057993bb50
commit
16957188b7
13 files changed
+499
-216
No files matched your search
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-mosdns
|
||||
PKG_VERSION:=1.7.11
|
||||
PKG_RELEASE:=19
|
||||
PKG_VERSION:=1.7.12
|
||||
PKG_RELEASE:=20
|
||||
|
||||
LUCI_TITLE:=LuCI Support for mosdns
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -48,6 +48,10 @@ let nodeStats;
|
||||
let nodeTop;
|
||||
let nodeLogs;
|
||||
let autoStatusBadge;
|
||||
let statsElements = null;
|
||||
let currentBadgeState = null;
|
||||
let lastTopJson = '';
|
||||
let lastLogsJson = '';
|
||||
|
||||
const cleanIP = ip => {
|
||||
if (!ip) return '-';
|
||||
@@ -66,9 +70,10 @@ const injectStyles = () => {
|
||||
'.mosdns-stat-card .title-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; font-size: 0.85rem; opacity: 0.75; font-weight: 500; }',
|
||||
'.mosdns-stat-card .metric-val { font-size: 1.85rem; font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; }',
|
||||
'.mosdns-stat-card .subtext { font-size: 0.8rem; opacity: 0.6; margin-top: 0.4rem; }',
|
||||
'.mosdns-sparkline-wrap { margin-top: 0.5rem; height: 44px; position: relative; overflow: visible; display: flex; align-items: flex-end; }',
|
||||
'.mosdns-sparkline-wrap { margin-top: 0.5rem; height: 44px; position: relative; overflow: visible; display: flex; align-items: flex-end; touch-action: none; -webkit-user-select: none; user-select: none; }',
|
||||
'.mosdns-sparkline { width: 100%; height: 100%; display: block; overflow: visible; }',
|
||||
'.mosdns-sparkline-tooltip { position: absolute; pointer-events: none; z-index: 20; padding: 0.25rem 0.5rem; border-radius: 5px; background: var(--cbi-section-bg, #fff); border: 1px solid rgba(0,0,0,0.12); box-shadow: 0 3px 10px rgba(0,0,0,0.12); line-height: 1.25; text-align: center; white-space: nowrap; transition: opacity 0.15s ease; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }',
|
||||
'.spark-hover-hitbox { touch-action: none; -webkit-user-select: none; user-select: none; cursor: crosshair; }',
|
||||
'.mosdns-rank-panel { background: var(--cbi-section-bg, #fff); border: 1px solid rgba(0,0,0,0.08); border-radius: 8px; padding: 1rem 1.1rem; box-shadow: 0 2px 6px rgba(0,0,0,0.03); }',
|
||||
'.mosdns-rank-panel h4 { margin: 0 0 0.85rem 0; font-size: 0.95rem; font-weight: 600; display: flex; align-items: center; justify-content: space-between; }',
|
||||
'.mosdns-rank-item { position: relative; overflow: hidden; border-radius: 6px; padding: 0.35rem 0.65rem; display: flex; justify-content: space-between; align-items: center; background: rgba(125,125,125,0.03); border: 1px solid rgba(125,125,125,0.08); margin-bottom: 0.35rem; }',
|
||||
@@ -143,7 +148,15 @@ const getLatencyClass = elapsedMs => {
|
||||
|
||||
const updateLiveStatusBadge = () => {
|
||||
if (!autoStatusBadge) return;
|
||||
if (pageIdx === 0 && !searchVal && !isUserPaused) {
|
||||
const isLive = (pageIdx === 0 && !searchVal && !isUserPaused);
|
||||
const targetState = isLive ? 'live' : ('paused:' + pageIdx);
|
||||
|
||||
if (currentBadgeState === targetState)
|
||||
return;
|
||||
|
||||
currentBadgeState = targetState;
|
||||
|
||||
if (isLive) {
|
||||
dom.content(autoStatusBadge, [
|
||||
E('span', { class: 'mosdns-badge badge-teal badge-pulse' }, _('● Live Auto-refresh'))
|
||||
]);
|
||||
@@ -154,47 +167,17 @@ const updateLiveStatusBadge = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const createSparklineSVG = (dataItems, strokeColor, fillGradId, maxScale) => {
|
||||
const createSparklineSVG = (strokeColor, fillGradId) => {
|
||||
const width = 300;
|
||||
const height = 44;
|
||||
const padTop = 4;
|
||||
const padBottom = 2;
|
||||
const drawHeight = height - padTop - padBottom;
|
||||
|
||||
let items = (dataItems && dataItems.length > 0) ? dataItems : [];
|
||||
if (!items.length) {
|
||||
items = new Array(24).fill(0).map(() => ({ time: '', val: 0 }));
|
||||
}
|
||||
if (items.length < 2) {
|
||||
items = [items[0] || { time: '', val: 0 }, items[0] || { time: '', val: 0 }];
|
||||
}
|
||||
|
||||
const vals = items.map(i => i.val || 0);
|
||||
const maxVal = maxScale || Math.max(...vals, 1);
|
||||
const len = items.length;
|
||||
|
||||
const coords = items.map((item, idx) => {
|
||||
const x = (idx / (len - 1)) * width;
|
||||
const y = height - padBottom - ((item.val || 0) / maxVal) * drawHeight;
|
||||
return { x, y, time: item.time, val: item.val || 0 };
|
||||
});
|
||||
|
||||
let pathD = 'M ' + coords[0].x.toFixed(1) + ',' + coords[0].y.toFixed(1);
|
||||
for (let i = 0; i < coords.length - 1; i++) {
|
||||
const p0 = coords[i === 0 ? 0 : i - 1];
|
||||
const p1 = coords[i];
|
||||
const p2 = coords[i + 1];
|
||||
const p3 = coords[i + 2 < coords.length ? i + 2 : i + 1];
|
||||
|
||||
const cp1x = p1.x + (p2.x - p0.x) / 6;
|
||||
const cp1y = p1.y + (p2.y - p0.y) / 6;
|
||||
const cp2x = p2.x - (p3.x - p1.x) / 6;
|
||||
const cp2y = p2.y - (p3.y - p1.y) / 6;
|
||||
|
||||
pathD += ' C ' + cp1x.toFixed(1) + ',' + cp1y.toFixed(1) + ' ' + cp2x.toFixed(1) + ',' + cp2y.toFixed(1) + ' ' + p2.x.toFixed(1) + ',' + p2.y.toFixed(1);
|
||||
}
|
||||
|
||||
const areaD = pathD + ' L ' + width + ',' + height + ' L 0,' + height + ' Z';
|
||||
let coords = [];
|
||||
let isHovered = false;
|
||||
let currentIdx = -1;
|
||||
let hideTimer = null;
|
||||
|
||||
const svgContainer = E('div', { class: 'mosdns-sparkline-wrap' });
|
||||
svgContainer.innerHTML =
|
||||
@@ -205,27 +188,26 @@ const createSparklineSVG = (dataItems, strokeColor, fillGradId, maxScale) => {
|
||||
'<stop offset="100%" stop-color="' + strokeColor + '" stop-opacity="0.02" />' +
|
||||
'</linearGradient>' +
|
||||
'</defs>' +
|
||||
'<path d="' + areaD + '" fill="url(#' + fillGradId + ')" />' +
|
||||
'<path d="' + pathD + '" fill="none" stroke="' + strokeColor + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />' +
|
||||
'<path class="spark-area-path" fill="url(#' + fillGradId + ')" />' +
|
||||
'<path class="spark-line-path" fill="none" stroke="' + strokeColor + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />' +
|
||||
'<g class="spark-hover-group" style="display: none;">' +
|
||||
'<line class="spark-hover-line" x1="0" y1="' + padTop + '" x2="0" y2="' + (height - padBottom) + '" stroke="' + strokeColor + '" stroke-width="1.2" stroke-dasharray="2 2" opacity="0.6" />' +
|
||||
'<circle class="spark-hover-dot" cx="0" cy="0" r="3.5" fill="' + strokeColor + '" stroke="#fff" stroke-width="1.5" />' +
|
||||
'</g>' +
|
||||
'<rect width="' + width + '" height="' + height + '" fill="transparent" class="spark-hover-hitbox" style="cursor: crosshair;" />' +
|
||||
'<rect width="' + width + '" height="' + height + '" fill="transparent" class="spark-hover-hitbox" />' +
|
||||
'</svg>' +
|
||||
'<div class="mosdns-sparkline-tooltip" style="display: none;"></div>';
|
||||
|
||||
const areaPath = svgContainer.querySelector('.spark-area-path');
|
||||
const linePath = svgContainer.querySelector('.spark-line-path');
|
||||
const hoverGroup = svgContainer.querySelector('.spark-hover-group');
|
||||
const hoverLine = svgContainer.querySelector('.spark-hover-line');
|
||||
const hoverDot = svgContainer.querySelector('.spark-hover-dot');
|
||||
const hitbox = svgContainer.querySelector('.spark-hover-hitbox');
|
||||
const tooltip = svgContainer.querySelector('.mosdns-sparkline-tooltip');
|
||||
|
||||
const onMove = e => {
|
||||
const rect = svgContainer.getBoundingClientRect();
|
||||
const mouseX = e.clientX - rect.left;
|
||||
const ratio = Math.max(0, Math.min(1, mouseX / rect.width));
|
||||
const idx = Math.round(ratio * (len - 1));
|
||||
const renderTooltipAndHover = idx => {
|
||||
if (idx < 0 || idx >= coords.length) return;
|
||||
const coord = coords[idx];
|
||||
if (!coord) return;
|
||||
|
||||
@@ -251,10 +233,14 @@ const createSparklineSVG = (dataItems, strokeColor, fillGradId, maxScale) => {
|
||||
'<div style="font-size: 0.72rem; opacity: 0.75; margin-top: 0.15rem;">' + timeStr + '</div>';
|
||||
tooltip.style.display = 'block';
|
||||
|
||||
const tooltipX = (coord.x / width) * rect.width;
|
||||
const rect = svgContainer.getBoundingClientRect();
|
||||
const containerWidth = rect.width || width;
|
||||
const tooltipX = (coord.x / width) * containerWidth;
|
||||
const ratio = coord.x / width;
|
||||
|
||||
if (ratio > 0.65) {
|
||||
tooltip.style.left = 'auto';
|
||||
tooltip.style.right = (rect.width - tooltipX + 8) + 'px';
|
||||
tooltip.style.right = (containerWidth - tooltipX + 8) + 'px';
|
||||
} else {
|
||||
tooltip.style.left = (tooltipX + 8) + 'px';
|
||||
tooltip.style.right = 'auto';
|
||||
@@ -262,21 +248,203 @@ const createSparklineSVG = (dataItems, strokeColor, fillGradId, maxScale) => {
|
||||
tooltip.style.top = '-6px';
|
||||
};
|
||||
|
||||
const onLeave = () => {
|
||||
hoverGroup.style.display = 'none';
|
||||
tooltip.style.display = 'none';
|
||||
const update = (dataItems, maxScale) => {
|
||||
let items = (dataItems && dataItems.length > 0) ? dataItems : [];
|
||||
if (!items.length) {
|
||||
items = new Array(24).fill(0).map(() => ({ time: '', val: 0 }));
|
||||
}
|
||||
if (items.length < 2) {
|
||||
items = [items[0] || { time: '', val: 0 }, items[0] || { time: '', val: 0 }];
|
||||
}
|
||||
|
||||
const vals = items.map(i => i.val || 0);
|
||||
const maxVal = maxScale || Math.max(...vals, 1);
|
||||
const len = items.length;
|
||||
|
||||
coords = items.map((item, idx) => {
|
||||
const x = (idx / (len - 1)) * width;
|
||||
const y = height - padBottom - ((item.val || 0) / maxVal) * drawHeight;
|
||||
return { x, y, time: item.time, val: item.val || 0 };
|
||||
});
|
||||
|
||||
let pathD = 'M ' + coords[0].x.toFixed(1) + ',' + coords[0].y.toFixed(1);
|
||||
for (let i = 0; i < coords.length - 1; i++) {
|
||||
const p0 = coords[i === 0 ? 0 : i - 1];
|
||||
const p1 = coords[i];
|
||||
const p2 = coords[i + 1];
|
||||
const p3 = coords[i + 2 < coords.length ? i + 2 : i + 1];
|
||||
|
||||
const cp1x = p1.x + (p2.x - p0.x) / 6;
|
||||
const cp1y = p1.y + (p2.y - p0.y) / 6;
|
||||
const cp2x = p2.x - (p3.x - p1.x) / 6;
|
||||
const cp2y = p2.y - (p3.y - p1.y) / 6;
|
||||
|
||||
pathD += ' C ' + cp1x.toFixed(1) + ',' + cp1y.toFixed(1) + ' ' + cp2x.toFixed(1) + ',' + cp2y.toFixed(1) + ' ' + p2.x.toFixed(1) + ',' + p2.y.toFixed(1);
|
||||
}
|
||||
|
||||
const areaD = pathD + ' L ' + width + ',' + height + ' L 0,' + height + ' Z';
|
||||
|
||||
areaPath.setAttribute('d', areaD);
|
||||
linePath.setAttribute('d', pathD);
|
||||
|
||||
if (isHovered && currentIdx >= 0) {
|
||||
renderTooltipAndHover(currentIdx);
|
||||
}
|
||||
};
|
||||
|
||||
hitbox.addEventListener('mousemove', onMove);
|
||||
hitbox.addEventListener('mouseleave', onLeave);
|
||||
const onPositionMove = clientX => {
|
||||
if (hideTimer) {
|
||||
clearTimeout(hideTimer);
|
||||
hideTimer = null;
|
||||
}
|
||||
const rect = svgContainer.getBoundingClientRect();
|
||||
if (!rect.width || !coords.length) return;
|
||||
const mouseX = clientX - rect.left;
|
||||
const ratio = Math.max(0, Math.min(1, mouseX / rect.width));
|
||||
const idx = Math.round(ratio * (coords.length - 1));
|
||||
currentIdx = idx;
|
||||
isHovered = true;
|
||||
renderTooltipAndHover(idx);
|
||||
};
|
||||
|
||||
const onLeave = (delay = 0) => {
|
||||
if (delay > 0) {
|
||||
if (hideTimer) clearTimeout(hideTimer);
|
||||
hideTimer = setTimeout(() => {
|
||||
isHovered = false;
|
||||
currentIdx = -1;
|
||||
hoverGroup.style.display = 'none';
|
||||
tooltip.style.display = 'none';
|
||||
hideTimer = null;
|
||||
}, delay);
|
||||
} else {
|
||||
if (hideTimer) {
|
||||
clearTimeout(hideTimer);
|
||||
hideTimer = null;
|
||||
}
|
||||
isHovered = false;
|
||||
currentIdx = -1;
|
||||
hoverGroup.style.display = 'none';
|
||||
tooltip.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
hitbox.addEventListener('mousemove', e => onPositionMove(e.clientX));
|
||||
hitbox.addEventListener('mouseenter', e => onPositionMove(e.clientX));
|
||||
hitbox.addEventListener('mouseleave', () => onLeave(0));
|
||||
|
||||
hitbox.addEventListener('touchstart', e => {
|
||||
if (e.touches && e.touches.length > 0) {
|
||||
onPositionMove(e.touches[0].clientX);
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
hitbox.addEventListener('touchmove', e => {
|
||||
if (e.touches && e.touches.length > 0) {
|
||||
onPositionMove(e.touches[0].clientX);
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
hitbox.addEventListener('touchend', () => onLeave(1500), { passive: true });
|
||||
hitbox.addEventListener('touchcancel', () => onLeave(0), { passive: true });
|
||||
|
||||
svgContainer.update = update;
|
||||
return svgContainer;
|
||||
};
|
||||
|
||||
const renderOverviewStats = (stats, historyData) => {
|
||||
const createOverviewStatsDOM = () => {
|
||||
const metricTotal = E('div', { class: 'metric-val' }, '-');
|
||||
const subtextTotal = E('div', { class: 'subtext' }, '-');
|
||||
const sparklineTotal = createSparklineSVG('#3b82f6', 'spark-grad-total');
|
||||
|
||||
const badgeBlocked = E('span', { class: 'mosdns-badge badge-danger' }, '-');
|
||||
const metricBlocked = E('div', { class: 'metric-val', style: 'color: #dc2626;' }, '-');
|
||||
const sparklineBlocked = createSparklineSVG('#dc2626', 'spark-grad-blocked');
|
||||
|
||||
const badgeCached = E('span', { class: 'mosdns-badge badge-teal' }, '-');
|
||||
const metricCached = E('div', { class: 'metric-val', style: 'color: #059669;' }, '-');
|
||||
const sparklineCached = createSparklineSVG('#059669', 'spark-grad-cached');
|
||||
|
||||
const metricLatency = E('div', { class: 'metric-val', style: 'color: #2563eb;' }, '-');
|
||||
const subtextLatency = E('div', { class: 'subtext' }, _('Per-query speed'));
|
||||
|
||||
const grid = E('div', { class: 'mosdns-grid' }, [
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('DNS Queries Total')),
|
||||
E('span', { class: 'mosdns-badge badge-teal badge-pulse' }, _('● Live'))
|
||||
]),
|
||||
metricTotal,
|
||||
subtextTotal
|
||||
]),
|
||||
sparklineTotal
|
||||
]),
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Blocked by Filters')),
|
||||
badgeBlocked
|
||||
]),
|
||||
metricBlocked
|
||||
]),
|
||||
sparklineBlocked
|
||||
]),
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Cached Queries')),
|
||||
badgeCached
|
||||
]),
|
||||
metricCached
|
||||
]),
|
||||
sparklineCached
|
||||
]),
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Average Processing Time')),
|
||||
E('span', { class: 'mosdns-badge badge-primary' }, _('Latency'))
|
||||
]),
|
||||
metricLatency,
|
||||
subtextLatency
|
||||
])
|
||||
])
|
||||
]);
|
||||
|
||||
statsElements = {
|
||||
grid,
|
||||
metricTotal,
|
||||
subtextTotal,
|
||||
sparklineTotal,
|
||||
badgeBlocked,
|
||||
metricBlocked,
|
||||
sparklineBlocked,
|
||||
badgeCached,
|
||||
metricCached,
|
||||
sparklineCached,
|
||||
metricLatency,
|
||||
subtextLatency
|
||||
};
|
||||
|
||||
return grid;
|
||||
};
|
||||
|
||||
const updateOverviewStats = (stats, historyData) => {
|
||||
if (!stats || stats.error) {
|
||||
return E('div', { class: 'alert-message warning' },
|
||||
_('MosDNS API is unreachable. Please ensure MosDNS is running and stats_api plugin is enabled.'));
|
||||
if (nodeStats) {
|
||||
dom.content(nodeStats, E('div', { class: 'alert-message warning' },
|
||||
_('MosDNS API is unreachable. Please ensure MosDNS is running and stats_api plugin is enabled.')));
|
||||
statsElements = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!statsElements || !nodeStats.contains(statsElements.grid)) {
|
||||
dom.content(nodeStats, createOverviewStatsDOM());
|
||||
}
|
||||
|
||||
const {
|
||||
@@ -295,52 +463,19 @@ const renderOverviewStats = (stats, historyData) => {
|
||||
|
||||
const baseMax = Math.max(...totalItems.map(i => i.val), 1);
|
||||
|
||||
return E('div', { class: 'mosdns-grid' }, [
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('DNS Queries Total')),
|
||||
E('span', { class: 'mosdns-badge badge-teal badge-pulse' }, _('● Live'))
|
||||
]),
|
||||
E('div', { class: 'metric-val' }, total.toLocaleString()),
|
||||
E('div', { class: 'subtext' }, _('Avg Processing') + ': ' + avg_ms + ' ms')
|
||||
]),
|
||||
createSparklineSVG(totalItems, '#3b82f6', 'spark-grad-total', baseMax)
|
||||
]),
|
||||
statsElements.metricTotal.textContent = total.toLocaleString();
|
||||
statsElements.subtextTotal.textContent = _('Avg Processing') + ': ' + avg_ms + ' ms';
|
||||
statsElements.sparklineTotal.update(totalItems, baseMax);
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Blocked by Filters')),
|
||||
E('span', { class: 'mosdns-badge badge-danger' }, blocked_pct + '%')
|
||||
]),
|
||||
E('div', { class: 'metric-val', style: 'color: #dc2626;' }, blocked.toLocaleString())
|
||||
]),
|
||||
createSparklineSVG(blockedItems, '#dc2626', 'spark-grad-blocked', baseMax)
|
||||
]),
|
||||
statsElements.badgeBlocked.textContent = blocked_pct + '%';
|
||||
statsElements.metricBlocked.textContent = blocked.toLocaleString();
|
||||
statsElements.sparklineBlocked.update(blockedItems, baseMax);
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Cached Queries')),
|
||||
E('span', { class: 'mosdns-badge badge-teal' }, cached_pct + '%')
|
||||
]),
|
||||
E('div', { class: 'metric-val', style: 'color: #059669;' }, cached.toLocaleString())
|
||||
]),
|
||||
createSparklineSVG(cachedItems, '#059669', 'spark-grad-cached', baseMax)
|
||||
]),
|
||||
statsElements.badgeCached.textContent = cached_pct + '%';
|
||||
statsElements.metricCached.textContent = cached.toLocaleString();
|
||||
statsElements.sparklineCached.update(cachedItems, baseMax);
|
||||
|
||||
E('div', { class: 'mosdns-stat-card' }, [
|
||||
E('div', {}, [
|
||||
E('div', { class: 'title-row' }, [
|
||||
E('span', {}, _('Average Processing Time')),
|
||||
E('span', { class: 'mosdns-badge badge-primary' }, _('Latency'))
|
||||
]),
|
||||
E('div', { class: 'metric-val', style: 'color: #2563eb;' }, avg_ms + ' ms'),
|
||||
E('div', { class: 'subtext' }, _('Per-query speed'))
|
||||
])
|
||||
])
|
||||
]);
|
||||
statsElements.metricLatency.textContent = avg_ms + ' ms';
|
||||
};
|
||||
|
||||
const renderTopRankings = topData => {
|
||||
@@ -398,6 +533,13 @@ const renderTopRankings = topData => {
|
||||
]);
|
||||
};
|
||||
|
||||
const updateTopRankings = topData => {
|
||||
const json = JSON.stringify(topData || {});
|
||||
if (json === lastTopJson) return;
|
||||
lastTopJson = json;
|
||||
dom.content(nodeTop, renderTopRankings(topData));
|
||||
};
|
||||
|
||||
const showLogDetailsModal = item => {
|
||||
let statusBadge;
|
||||
if (item.is_blocked) {
|
||||
@@ -579,12 +721,16 @@ const pollScheduler = async () => {
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
dom.content(nodeStats, renderOverviewStats(results[0], results[2]));
|
||||
dom.content(nodeTop, renderTopRankings(results[1]));
|
||||
updateOverviewStats(results[0], results[2]);
|
||||
updateTopRankings(results[1]);
|
||||
|
||||
if (shouldRefreshLogs && results[3]) {
|
||||
const json = JSON.stringify(results[3]);
|
||||
if (json !== lastLogsJson) {
|
||||
lastLogsJson = json;
|
||||
dom.content(nodeLogs, renderLogsTable(results[3]));
|
||||
}
|
||||
}
|
||||
updateLiveStatusBadge();
|
||||
} catch (e) {
|
||||
}
|
||||
@@ -593,6 +739,7 @@ const pollScheduler = async () => {
|
||||
const refreshLogs = async () => {
|
||||
try {
|
||||
const logs = await callGetLogs(PAGE_SIZE, pageIdx * PAGE_SIZE, searchVal, filterVal);
|
||||
lastLogsJson = JSON.stringify(logs || {});
|
||||
dom.content(nodeLogs, renderLogsTable(logs));
|
||||
updateLiveStatusBadge();
|
||||
} catch (e) {
|
||||
@@ -613,13 +760,19 @@ return view.extend({
|
||||
render(data) {
|
||||
injectStyles();
|
||||
|
||||
statsElements = null;
|
||||
currentBadgeState = null;
|
||||
lastTopJson = '';
|
||||
lastLogsJson = '';
|
||||
|
||||
nodeStats = E('div', { id: 'overview-stats' });
|
||||
nodeTop = E('div', { id: 'top-rankings' });
|
||||
nodeLogs = E('div', { id: 'logs-table' });
|
||||
autoStatusBadge = E('div', { style: 'display: inline-block;' });
|
||||
|
||||
dom.content(nodeStats, renderOverviewStats(data[0], data[3]));
|
||||
dom.content(nodeTop, renderTopRankings(data[1]));
|
||||
updateOverviewStats(data[0], data[3]);
|
||||
updateTopRankings(data[1]);
|
||||
lastLogsJson = JSON.stringify(data[2] || {});
|
||||
dom.content(nodeLogs, renderLogsTable(data[2]));
|
||||
updateLiveStatusBadge();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.8.26
|
||||
PKG_RELEASE:=254
|
||||
PKG_RELEASE:=255
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -1810,18 +1810,7 @@ function gen_config(var)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(route.rules, {
|
||||
action = "route",
|
||||
ip_is_private = true,
|
||||
outbound = "direct"
|
||||
})
|
||||
|
||||
if COMMON.default_outbound_tag then
|
||||
table.insert(route.rules, {
|
||||
action = "route",
|
||||
port_range = { "0:65535" },
|
||||
outbound = COMMON.default_outbound_tag
|
||||
})
|
||||
route.final = COMMON.default_outbound_tag
|
||||
end
|
||||
|
||||
|
||||
@@ -1540,11 +1540,6 @@ function gen_config(var)
|
||||
})
|
||||
end
|
||||
|
||||
table.insert(rules, {
|
||||
outboundTag = "direct",
|
||||
ip = { "geoip:private" }
|
||||
})
|
||||
|
||||
if default_outboundTag then
|
||||
local rule = {
|
||||
_flag = "default",
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.8.27
|
||||
PKG_RELEASE:=106
|
||||
PKG_RELEASE:=107
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -1797,11 +1797,6 @@ function gen_config(var)
|
||||
end
|
||||
|
||||
if COMMON.default_outbound_tag then
|
||||
table.insert(route.rules, {
|
||||
action = "route",
|
||||
port_range = { "0:65535" },
|
||||
outbound = COMMON.default_outbound_tag
|
||||
})
|
||||
route.final = COMMON.default_outbound_tag
|
||||
end
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap
|
||||
FOOTSTRAP_VERSION?=
|
||||
ifneq ($(FOOTSTRAP_VERSION),)
|
||||
PKG_VERSION:=$(FOOTSTRAP_VERSION)
|
||||
PKG_RELEASE:=48
|
||||
PKG_RELEASE:=49
|
||||
endif
|
||||
|
||||
LUCI_TITLE:=Footstrap Theme
|
||||
|
||||
@@ -130,6 +130,18 @@ function naturalHeight(el) {
|
||||
const last = el.lastElementChild;
|
||||
if (!last) return 0;
|
||||
const box = el.getBoundingClientRect();
|
||||
/* A BOX WITH NO HEIGHT OF ITS OWN HOLDS NOTHING UP, and asking its content how tall it would be
|
||||
* gets an answer about a page that is not on screen. `visibility: hidden` leaves children in the
|
||||
* layout with rects of their own, so an inactive tab pane — collapsed to height 0 by
|
||||
* theme/30-tables.css — measures its full content here and the floor then pins that collapse
|
||||
* open: on Network -> Interfaces the hidden `device` pane held 893px, and the active pane's
|
||||
* content sat that much further down the page (issue #41, reported against a third-party page
|
||||
* and reproduced on the stock one). The clear-and-remeasure shape this replaced read the
|
||||
* collapsed height and wrote nothing, which is the behaviour restored here.
|
||||
*
|
||||
* A container a tick has just emptied also measures 0, and that is the same answer for the same
|
||||
* reason: the floor it already wears is what holds it up, and holdFloor() leaves it alone. */
|
||||
if (!box.height) return 0;
|
||||
const end = last.getBoundingClientRect();
|
||||
if (!end.height && !end.width) return 0; /* a last child out of the flow says nothing */
|
||||
const cs = window.getComputedStyle(el);
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ MISE_HASH_x86_64:=3832f39c325e343f81fe3d92b2447c5d1a5eea1bc85092bb7b6c2580622264
|
||||
MISE_HASH_aarch64:=06186cfbfe947049b21d58575fb0ea800cc26ed1375f20f4b678cb3a9d679437
|
||||
|
||||
PKG_NAME:=mise
|
||||
PKG_VERSION:=2026.8.15
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=2026.8.16
|
||||
PKG_RELEASE:=3
|
||||
PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION)-linux-$(MISE_ARCH)-musl.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/jdx/mise/releases/download/v$(PKG_VERSION)/
|
||||
PKG_HASH:=skip
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mosdns
|
||||
PKG_VERSION:=5.3.4
|
||||
PKG_RELEASE:=19
|
||||
PKG_RELEASE:=20
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/v$(PKG_VERSION)?
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From 201408484de552cb927f6a50b76a34d65c8ac8c6 Mon Sep 17 00:00:00 2001
|
||||
From 4b76512586cd404855b717d6b8ac3b4d12ef7a54 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Fri, 20 Mar 2026 10:39:22 +0800
|
||||
Subject: [PATCH] mosdns: update dependencies
|
||||
@@ -7,10 +7,10 @@ Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
.github/workflows/release.yml | 2 +-
|
||||
.github/workflows/test.yml | 2 +-
|
||||
go.mod | 36 +++++++++----------
|
||||
go.sum | 68 +++++++++++++++++------------------
|
||||
go.mod | 60 ++++++++---------
|
||||
go.sum | 121 ++++++++++++++++------------------
|
||||
pkg/query_context/context.go | 1 -
|
||||
5 files changed, 54 insertions(+), 55 deletions(-)
|
||||
5 files changed, 85 insertions(+), 101 deletions(-)
|
||||
|
||||
--- a/.github/workflows/release.yml
|
||||
+++ b/.github/workflows/release.yml
|
||||
@@ -36,107 +36,132 @@ Signed-off-by: sbwml <admin@cooluc.com>
|
||||
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1,30 +1,30 @@
|
||||
@@ -1,31 +1,31 @@
|
||||
module github.com/IrineSistiana/mosdns/v5
|
||||
|
||||
-go 1.24.9
|
||||
+go 1.25.0
|
||||
+go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57
|
||||
- github.com/go-chi/chi/v5 v5.2.3
|
||||
- github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
+ github.com/go-chi/chi/v5 v5.2.5
|
||||
+ github.com/go-chi/chi/v5 v5.3.2
|
||||
+ github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/google/nftables v0.3.0
|
||||
github.com/kardianos/service v1.2.4
|
||||
- github.com/kardianos/service v1.2.4
|
||||
- github.com/klauspost/compress v1.18.2
|
||||
- github.com/miekg/dns v1.1.70
|
||||
+ github.com/klauspost/compress v1.18.4
|
||||
+ github.com/miekg/dns v1.1.72
|
||||
+ github.com/kardianos/service v1.3.0
|
||||
+ github.com/klauspost/compress v1.19.2
|
||||
+ github.com/miekg/dns v1.1.73
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nadoo/ipset v0.5.0
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
- github.com/prometheus/client_golang v1.23.2
|
||||
- github.com/quic-go/quic-go v0.58.1
|
||||
+ github.com/quic-go/quic-go v0.59.0
|
||||
+ github.com/prometheus/client_golang v1.24.1
|
||||
+ github.com/quic-go/quic-go v0.62.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
- github.com/stretchr/testify v1.11.1
|
||||
+ github.com/stretchr/testify v1.12.1
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
go.uber.org/zap v1.27.1
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
- go.uber.org/zap v1.27.1
|
||||
- go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
- golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
|
||||
- golang.org/x/net v0.48.0
|
||||
- golang.org/x/sync v0.19.0
|
||||
- golang.org/x/sys v0.40.0
|
||||
- golang.org/x/time v0.14.0
|
||||
+ golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90
|
||||
+ golang.org/x/net v0.52.0
|
||||
+ golang.org/x/sync v0.20.0
|
||||
+ golang.org/x/sys v0.42.0
|
||||
- google.golang.org/protobuf v1.36.11
|
||||
+ go.uber.org/zap v1.28.0
|
||||
+ go4.org/netipx v0.0.0-20260823151212-3075585bcbeb
|
||||
+ golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa
|
||||
+ golang.org/x/net v0.58.0
|
||||
+ golang.org/x/sync v0.22.0
|
||||
+ golang.org/x/sys v0.47.0
|
||||
+ golang.org/x/time v0.15.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
+ google.golang.org/protobuf v1.36.12
|
||||
)
|
||||
|
||||
@@ -37,14 +37,14 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
replace github.com/nadoo/ipset v0.5.0 => github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a
|
||||
@@ -33,18 +33,16 @@ replace github.com/nadoo/ipset v0.5.0 =>
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
- github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
- github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
+ github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
- github.com/mdlayher/netlink v1.8.0 // indirect
|
||||
+ github.com/mdlayher/netlink v1.9.0 // indirect
|
||||
github.com/mdlayher/socket v0.5.1 // indirect
|
||||
- github.com/mdlayher/socket v0.5.1 // indirect
|
||||
+ github.com/mdlayher/netlink v1.11.2 // indirect
|
||||
+ github.com/mdlayher/socket v0.6.1 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
- github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
- github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
- github.com/prometheus/client_model v0.6.2 // indirect
|
||||
- github.com/prometheus/common v0.67.5 // indirect
|
||||
- github.com/prometheus/procfs v0.19.2 // indirect
|
||||
+ github.com/prometheus/procfs v0.20.1 // indirect
|
||||
+ github.com/pelletier/go-toml/v2 v2.4.3 // indirect
|
||||
+ github.com/prometheus/client_model v0.6.3 // indirect
|
||||
+ github.com/prometheus/common v0.71.0 // indirect
|
||||
+ github.com/prometheus/procfs v0.22.0 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
@@ -55,11 +55,11 @@ require (
|
||||
@@ -55,11 +53,7 @@ require (
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
- go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
+ go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
- go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
- golang.org/x/crypto v0.46.0 // indirect
|
||||
- golang.org/x/mod v0.32.0 // indirect
|
||||
- golang.org/x/text v0.33.0 // indirect
|
||||
- golang.org/x/tools v0.40.0 // indirect
|
||||
+ golang.org/x/crypto v0.49.0 // indirect
|
||||
+ golang.org/x/mod v0.34.0 // indirect
|
||||
+ golang.org/x/text v0.35.0 // indirect
|
||||
+ golang.org/x/tools v0.43.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
- gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
+ go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
+ golang.org/x/crypto v0.55.0 // indirect
|
||||
+ golang.org/x/text v0.41.0 // indirect
|
||||
)
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -13,10 +13,10 @@ github.com/frankban/quicktest v1.14.6 h1
|
||||
@@ -7,58 +7,56 @@ github.com/beorn7/perks v1.0.1/go.mod h1
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
-github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
-github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
-github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
|
||||
-github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
-github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
-github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
+github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||
+github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||
+github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
|
||||
+github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
|
||||
+github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY=
|
||||
+github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
||||
+github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
+github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/nftables v0.3.0 h1:bkyZ0cbpVeMHXOrtlFc8ISmfVqq5gPJukoYieyVmITg=
|
||||
@@ -25,20 +25,20 @@ github.com/inconshreveable/mousetrap v1.
|
||||
github.com/google/nftables v0.3.0/go.mod h1:BCp9FsrbF1Fn/Yu6CLUc9GGZFw/+hsxfluNXXmxBfRM=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2OgBk=
|
||||
github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
-github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2OgBk=
|
||||
-github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
-github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
-github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
+github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||
+github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
+github.com/kardianos/service v1.3.0 h1:/LGy+xPP2TM+GLTiCZ2di7cy0Jd/qrawlTUfqKYFdTI=
|
||||
+github.com/kardianos/service v1.3.0/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
+github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8=
|
||||
+github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -145,46 +170,80 @@ Signed-off-by: sbwml <admin@cooluc.com>
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
-github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM=
|
||||
-github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594=
|
||||
+github.com/mdlayher/netlink v1.9.0 h1:G8+GLq2x3v4D4MVIqDdNUhTUC7TKiCy/6MDkmItfKco=
|
||||
+github.com/mdlayher/netlink v1.9.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
-github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
-github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
-github.com/miekg/dns v1.1.70 h1:DZ4u2AV35VJxdD9Fo9fIWm119BsQL5cZU1cQ9s0LkqA=
|
||||
-github.com/miekg/dns v1.1.70/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
|
||||
+github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
|
||||
+github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
|
||||
+github.com/mdlayher/netlink v1.11.2 h1:HKh2jqe+omdSWcQ88nrT7INE61B0NXfiSPFdgL4YbNI=
|
||||
+github.com/mdlayher/netlink v1.11.2/go.mod h1:uT2Yc/QLaZubzDpZIBi9d4GoeLwtp3x1AMeqSRrK2sA=
|
||||
+github.com/mdlayher/socket v0.6.1 h1:M7uj2NtuujUY4mYr1C57NmfNiRHbkKpnBxO856lsc3A=
|
||||
+github.com/mdlayher/socket v0.6.1/go.mod h1:+/SGtqc9V+5dAuRgQsU0fGBI+oRDiW7O2Obx10OIWfg=
|
||||
+github.com/miekg/dns v1.1.73 h1:uhT8nJxmTrPJYClxVxTCX+CVn6qnzSiybRk72Z6DgrE=
|
||||
+github.com/miekg/dns v1.1.73/go.mod h1:RW2Obtfd5NZHvOFe3zYG0W8koWOQtAzyHaLo8vASBuQ=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
@@ -53,12 +53,12 @@ github.com/prometheus/client_model v0.6.
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
-github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
-github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
-github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
-github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
-github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
-github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
-github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
-github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
-github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
-github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
+github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
+github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
+github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
|
||||
+github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
+github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
|
||||
+github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
|
||||
+github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo=
|
||||
+github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM=
|
||||
+github.com/prometheus/common v0.71.0 h1:9KDAKb7Mj3HEVKyFCK6Dc/HIwlBzZIN2l7/lrHl3KK8=
|
||||
+github.com/prometheus/common v0.71.0/go.mod h1:CLJ5H8TEsGX8bl31BdMkfhIZ+QmZ9tBPPotUxUbfcmk=
|
||||
+github.com/prometheus/procfs v0.22.0 h1:6q9+/JL9IKAPbCmBrv9n5O5Ty3NKnciV5X7YGw0oics=
|
||||
+github.com/prometheus/procfs v0.22.0/go.mod h1:CvmFr/GVhIjIvWJZW3tgkODBQMRIf0EyWMQLHCHab58=
|
||||
+github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0=
|
||||
+github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
-github.com/quic-go/quic-go v0.58.1 h1:J0s55TVauDbnCEY5tU2B8e7nYb3gnKMSez5Fwi1dl2s=
|
||||
-github.com/quic-go/quic-go v0.58.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
+github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
+github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
+github.com/quic-go/quic-go v0.62.0 h1:ZHDjCk5OacATwGvs8PWE97CTvX7AqZiVoW7++ZOXTf8=
|
||||
+github.com/quic-go/quic-go v0.62.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -91,32 +91,32 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSx
|
||||
@@ -75,8 +73,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2K
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
-github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
-github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
+github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||
+github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
@@ -89,38 +87,31 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5E
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
-go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
-go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
-go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
-go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
-go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
+go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo=
|
||||
+go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q=
|
||||
+go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
+go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
-go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||
-go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
-golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
-golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
-golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||
@@ -195,16 +254,18 @@ Signed-off-by: sbwml <admin@cooluc.com>
|
||||
-golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
-golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
-golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
+golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
+golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
+golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
|
||||
+golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
|
||||
+golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
+golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
+golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
+golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
+golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
+go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
+go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
+go4.org/netipx v0.0.0-20260823151212-3075585bcbeb h1:XBM4hvfwGAttkkiTIFfeigdfcL1xIfdKXqFdgiHGtDs=
|
||||
+go4.org/netipx v0.0.0-20260823151212-3075585bcbeb/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
+golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
||||
+golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
||||
+golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa h1:QSyA8ishJCyT21kER9KwNt0b7BM3iRK4x9QXhjN5Fdk=
|
||||
+golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM=
|
||||
+golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||
+golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||
+golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||
+golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
-golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
@@ -215,17 +276,21 @@ Signed-off-by: sbwml <admin@cooluc.com>
|
||||
-golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
-golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
-golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
+golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
+golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
-google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
-google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
+golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
+golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
+golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||
+golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
+golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
+golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
+golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||
+golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
+google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
+google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
--- a/pkg/query_context/context.go
|
||||
+++ b/pkg/query_context/context.go
|
||||
@@ -108,7 +108,6 @@ func (ctx *Context) QQuestion() dns.Ques
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
From 68799cf43340bf2e9e0b7145ea961d69ca45d6fe Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Mon, 31 Aug 2026 22:49:01 +0800
|
||||
Subject: [PATCH] feat(stats_api): exclude blocked queries from cache hit
|
||||
percentage
|
||||
|
||||
Calculate cache hit rate based on unblocked queries (total - blocked)
|
||||
instead of total queries to prevent ad blocking from skewing the stats.
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
plugin/executable/stats_api/stats_api.go | 7 +++-
|
||||
plugin/executable/stats_api/stats_api_test.go | 35 +++++++++++++++++++
|
||||
2 files changed, 41 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/plugin/executable/stats_api/stats_api.go
|
||||
+++ b/plugin/executable/stats_api/stats_api.go
|
||||
@@ -629,9 +629,14 @@ func (s *StatsAPI) handleStats(w http.Re
|
||||
var blockedPct, cachedPct, avgLat float64
|
||||
if total > 0 {
|
||||
blockedPct = float64(blocked) / float64(total) * 100.0
|
||||
- cachedPct = float64(cached) / float64(total) * 100.0
|
||||
avgLat = (float64(latUs) / float64(total)) / 1000.0
|
||||
}
|
||||
+ if total > blocked {
|
||||
+ cachedPct = float64(cached) / float64(total-blocked) * 100.0
|
||||
+ if cachedPct > 100.0 {
|
||||
+ cachedPct = 100.0
|
||||
+ }
|
||||
+ }
|
||||
|
||||
blockedPct = math.Round(blockedPct*100) / 100
|
||||
cachedPct = math.Round(cachedPct*100) / 100
|
||||
--- a/plugin/executable/stats_api/stats_api_test.go
|
||||
+++ b/plugin/executable/stats_api/stats_api_test.go
|
||||
@@ -511,3 +511,38 @@ func TestStatsAPINonExistentDumpFile(t *
|
||||
t.Errorf("expected 0 total queries, got %d", s.totalQueries.Load())
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestStatsAPICachedPercentageExcludesBlocked(t *testing.T) {
|
||||
+ s := NewStatsAPI(&Args{Capacity: 100}, zap.NewNop())
|
||||
+ router := s.Router()
|
||||
+
|
||||
+ // 100 total queries: 50 blocked, 25 cached, 25 forwarded to upstream
|
||||
+ s.totalQueries.Store(100)
|
||||
+ s.blockedQueries.Store(50)
|
||||
+ s.cachedQueries.Store(25)
|
||||
+ s.totalLatencyUs.Store(50000)
|
||||
+
|
||||
+ req := httptest.NewRequest(http.MethodGet, "/api/v1/stats", nil)
|
||||
+ w := httptest.NewRecorder()
|
||||
+ router.ServeHTTP(w, req)
|
||||
+
|
||||
+ if w.Code != http.StatusOK {
|
||||
+ t.Fatalf("expected HTTP 200, got %d", w.Code)
|
||||
+ }
|
||||
+
|
||||
+ var statsResp map[string]any
|
||||
+ if err := json.Unmarshal(w.Body.Bytes(), &statsResp); err != nil {
|
||||
+ t.Fatalf("failed to unmarshal stats response: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ // blocked_percentage = 50 / 100 = 50%
|
||||
+ if blockedPct := statsResp["blocked_percentage"].(float64); blockedPct != 50.0 {
|
||||
+ t.Errorf("expected blocked_percentage 50.0, got %v", blockedPct)
|
||||
+ }
|
||||
+
|
||||
+ // cached_percentage = 25 / (100 - 50) = 50% (previously 25%)
|
||||
+ if cachedPct := statsResp["cached_percentage"].(float64); cachedPct != 50.0 {
|
||||
+ t.Errorf("expected cached_percentage 50.0, got %v", cachedPct)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
Reference in new issue
Block a user