feat: rich ratelimited log viewer table
Renders ratelimited log entries as a structured table instead of raw JSON, showing: timestamp, sender (header_from), recipient, subject, IP address, rate-limit rule name (orange badge, tooltip with rl_info), and queue ID. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -913,6 +913,45 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Ratelimited log renderer ──────────────────────────────────────────
|
||||||
|
|
||||||
|
const renderRatelimitLog = (entries) => {
|
||||||
|
let html = `<div class="woocow-log-toolbar">
|
||||||
|
<strong>Rate-Limited Messages</strong>
|
||||||
|
<span style="color:#666;font-size:12px">${entries.length} entries</span>
|
||||||
|
</div>
|
||||||
|
<table class="wp-list-table widefat fixed striped woocow-table">
|
||||||
|
<thead><tr>
|
||||||
|
<th style="width:130px">Time</th>
|
||||||
|
<th>Sender</th>
|
||||||
|
<th>Recipient</th>
|
||||||
|
<th>Subject</th>
|
||||||
|
<th style="width:110px">IP</th>
|
||||||
|
<th style="width:120px">Rate Limit Rule</th>
|
||||||
|
<th style="width:110px">Queue ID</th>
|
||||||
|
</tr></thead><tbody>`;
|
||||||
|
|
||||||
|
entries.forEach(e => {
|
||||||
|
const dt = e.time ? new Date(e.time * 1000).toLocaleString() : '—';
|
||||||
|
const sender = e.header_from || e.from || '—';
|
||||||
|
const subject = e.header_subject || '—';
|
||||||
|
html += `<tr>
|
||||||
|
<td style="font-size:11px;white-space:nowrap">${esc(dt)}</td>
|
||||||
|
<td style="font-size:11px">${esc(sender)}</td>
|
||||||
|
<td style="font-size:11px">${esc(e.rcpt || '—')}</td>
|
||||||
|
<td style="font-size:12px">${esc(subject)}</td>
|
||||||
|
<td><code style="font-size:11px">${esc(e.ip || '—')}</code></td>
|
||||||
|
<td>
|
||||||
|
<span class="woocow-badge woocow-badge-orange" title="${esc(e.rl_info || '')}">${esc(e.rl_name || '—')}</span>
|
||||||
|
</td>
|
||||||
|
<td><code style="font-size:11px">${esc(e.qid || '—')}</code></td>
|
||||||
|
</tr>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
html += '</tbody></table>';
|
||||||
|
$('#wc-log-wrap').html(html);
|
||||||
|
};
|
||||||
|
|
||||||
// ── Log load ──────────────────────────────────────────────────────────
|
// ── Log load ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
$('#wc-log-load').on('click', () => {
|
$('#wc-log-load').on('click', () => {
|
||||||
@@ -931,10 +970,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'rspamd-history') {
|
if (type === 'rspamd-history') { renderRspamdLog(entries); return; }
|
||||||
renderRspamdLog(entries);
|
if (type === 'ratelimited') { renderRatelimitLog(entries); return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plain text log
|
// Plain text log
|
||||||
const typeLabel = $('#wc-log-type option:selected').text();
|
const typeLabel = $('#wc-log-type option:selected').text();
|
||||||
|
|||||||
Reference in New Issue
Block a user