guanghulab/guanghulab-main/scripts/process-syslog.js
2026-05-10 13:12:44 +08:00

139 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// scripts/process-syslog.js
// 铸渊 SYSLOG Pipeline
// 读取 syslog-inbox/ 下的日志条目,处理后归档到 syslog-processed/
// 触发syslog-inbox/ 目录有新文件 push 到 main 分支
'use strict';
const fs = require('fs');
const path = require('path');
const INBOX_DIR = 'syslog-inbox';
const ARCHIVE_DIR = 'syslog-processed';
const BRAIN_DIR = '.github/brain';
const MEMORY_PATH = path.join(BRAIN_DIR, 'memory.json');
const DEV_STATUS_PATH = '.github/persona-brain/dev-status.json';
// ─── 加载大脑 ────────────────────────────────────────────
let memory = {};
try {
memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8'));
} catch (_) {
memory = { events: [], stats: { broadcasts_processed: 0 } };
}
if (!memory.events) memory.events = [];
if (!memory.stats) memory.stats = {};
if (!memory.stats.broadcasts_processed) memory.stats.broadcasts_processed = 0;
if (!memory.stats.syslog_processed) memory.stats.syslog_processed = 0;
// ─── 扫描 inbox ──────────────────────────────────────────
if (!fs.existsSync(INBOX_DIR)) {
console.log('📭 syslog-inbox/ 目录不存在,跳过');
process.exit(0);
}
const files = fs.readdirSync(INBOX_DIR)
.filter(f => f.endsWith('.json') && f !== '.gitkeep');
if (files.length === 0) {
console.log('📭 syslog-inbox/ 无待处理条目');
process.exit(0);
}
console.log(`📥 发现 ${files.length} 条 syslog 条目,开始处理...\n`);
// ─── 按月归档路径 ─────────────────────────────────────────
function archiveDir(timestamp) {
const month = (timestamp || new Date().toISOString()).slice(0, 7); // "2026-03"
const dir = path.join(ARCHIVE_DIR, month);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
return dir;
}
// ─── 处理每条 syslog ──────────────────────────────────────
files.forEach(file => {
const fullPath = path.join(INBOX_DIR, file);
let entry;
try {
entry = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
} catch (e) {
console.error(`❌ [INVALID JSON] ${file}: ${e.message},跳过`);
return;
}
console.log(`📋 处理: ${file}`);
console.log(` 类型: ${entry.type || '未知'} · 来自: ${entry.from || '未知'} · 标题: ${entry.title || ''}`);
const event = {
timestamp: entry.timestamp || new Date().toISOString(),
type: 'syslog_' + (entry.type || 'unknown'),
syslog_id: entry.syslog_id || file,
title: entry.title || '(无标题)',
from: entry.from || '未知',
file,
};
// ── 根据类型分发处理 ──
switch (entry.type) {
case 'broadcast': {
// 广播类:追加到 brain/memory.json events与现有 broadcast pipeline 互补
memory.stats.broadcasts_processed += 1;
event.content_preview = (entry.content || '').slice(0, 80);
console.log(' ✅ 广播已记录到大脑记忆');
break;
}
case 'auth': {
// 授权类:记录授权事件,写入 memory
event.target_dev_id = entry.target_dev_id;
event.target_name = entry.target_name;
event.permission_level = entry.permission_level;
event.authorized_by = entry.authorized_by || '冰朔';
event.valid_until = entry.valid_until;
console.log(` ✅ 授权记录:${entry.target_name}${entry.target_dev_id})· 权限:${entry.permission_level}`);
break;
}
case 'inspect': {
// 巡检类:记录巡检结果
event.inspect_result = entry.result || 'unknown';
event.issues_found = entry.issues_found || 0;
console.log(` ✅ 巡检记录:结果 ${event.inspect_result} · 发现问题 ${event.issues_found}`);
break;
}
case 'alert': {
// 告警类
event.severity = entry.priority || 'normal';
console.log(` ⚠️ 告警记录:${entry.title} · 优先级 ${event.severity}`);
break;
}
default:
console.log(` 未知类型 "${entry.type}",已记录原始内容`);
event.raw = entry;
}
// 写入大脑记忆
memory.events.push(event);
memory.stats.syslog_processed = (memory.stats.syslog_processed || 0) + 1;
memory.last_updated = new Date().toISOString();
// 归档文件
const destDir = archiveDir(entry.timestamp);
const destPath = path.join(destDir, file);
fs.renameSync(fullPath, destPath);
console.log(` 📦 已归档到 ${destPath}\n`);
});
// ─── 保存大脑 ─────────────────────────────────────────────
// 只保留最近 100 条事件,防止 memory.json 无限膨胀
if (memory.events.length > 100) {
memory.events = memory.events.slice(-100);
}
fs.writeFileSync(MEMORY_PATH, JSON.stringify(memory, null, 2));
console.log(`✅ SYSLOG Pipeline 完成 · 累计处理 ${memory.stats.syslog_processed}`);