feat: system logs - email log + system log with admin UI
- db: email_logs (sent/failed) + system_logs (info/warn/error) tables, auto-migrated for existing installs - backend/logger.js: logEmail/logSystem with try/catch (never breaks flow) - mailer: log send result (SMTP unconfigured/sent/failed + error msg) - webhook: log blocked-internal, non-2xx response, send failure - server: error middleware records 500 errors to system_logs - routes/logs.js: GET /logs/emails + /logs/system (admin/owner, filters) - UI: 系统日志 page (owner/admin) with system/email tabs + filters - API docs updated
This commit is contained in:
28
backend/logger.js
Normal file
28
backend/logger.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// 日志模块: 邮件日志 + 系统日志, 写入数据库供后台查看
|
||||
// 所有写库操作 try/catch 包裹, 日志失败绝不影响主流程
|
||||
const { query } = require('./db');
|
||||
|
||||
// 系统日志: level = info | warn | error
|
||||
async function logSystem(level, source, message, details) {
|
||||
try {
|
||||
await query(
|
||||
'INSERT INTO system_logs(level, source, message, details) VALUES (?,?,?,?)',
|
||||
[level || 'info', String(source || '').slice(0, 50), String(message || '').slice(0, 2000),
|
||||
details ? JSON.stringify(details).slice(0, 4000) : null]
|
||||
);
|
||||
} catch { /* 日志失败忽略 */ }
|
||||
}
|
||||
|
||||
// 邮件日志: status = sent | failed
|
||||
async function logEmail(to, templateCode, subject, status, error) {
|
||||
try {
|
||||
await query(
|
||||
'INSERT INTO email_logs(to_email, template_code, subject, status, error) VALUES (?,?,?,?,?)',
|
||||
[String(to || '').slice(0, 100), String(templateCode || '').slice(0, 50),
|
||||
String(subject || '').slice(0, 255), status === 'sent' ? 'sent' : 'failed',
|
||||
error ? String(error).slice(0, 2000) : null]
|
||||
);
|
||||
} catch { /* 日志失败忽略 */ }
|
||||
}
|
||||
|
||||
module.exports = { logSystem, logEmail };
|
||||
Reference in New Issue
Block a user