feat: add frontend logging system with router and visibility tracking

This commit is contained in:
2025-10-05 11:59:17 -04:00
parent c0ebfcf5b9
commit 6c4febe205
25 changed files with 2309 additions and 7 deletions
+46
View File
@@ -430,6 +430,52 @@ app.get('/api/files/by-date-range', (req, res) => {
// Bookmarks API - reads/writes <vault>/.obsidian/bookmarks.json
app.use(express.json());
app.post('/api/log', (req, res) => {
try {
const payload = req.body;
if (!payload) {
return res.status(400).json({ error: 'Missing log payload' });
}
const records = Array.isArray(payload) ? payload : [payload];
records.forEach((record) => {
if (!record || typeof record !== 'object') {
console.warn('[FrontendLog] Ignored invalid record', record);
return;
}
const {
event = 'UNKNOWN_EVENT',
level = 'info',
sessionId,
userAgent,
context = {},
data,
} = record;
const summary = {
sessionId,
route: context?.route ?? 'n/a',
theme: context?.theme ?? 'n/a',
version: context?.version ?? 'n/a',
};
if (data !== undefined) {
summary.data = data;
}
console.log(`[FrontendLog:${level}]`, event, summary, userAgent ?? '');
});
return res.status(202).json({ ok: true });
} catch (error) {
console.error('Failed to process frontend logs:', error);
return res.status(500).json({ error: 'Failed to process logs' });
}
});
app.post('/api/logs', (req, res) => {
const { source = 'frontend', level = 'info', message = '', data = null, timestamp = Date.now() } = req.body || {};
+80
View File
@@ -0,0 +1,80 @@
/**
* Example backend endpoint for receiving frontend logs
* Add this to your Express server (server/index.mjs)
*/
// Add to your Express app:
/*
app.post('/api/log', express.json(), (req, res) => {
const logs = Array.isArray(req.body) ? req.body : [req.body];
logs.forEach(log => {
const timestamp = new Date(log.ts).toLocaleString();
const event = log.event.padEnd(30);
const data = JSON.stringify(log.data || {});
console.log(`[${timestamp}] ${event} ${data}`);
// Optional: Store in database, send to monitoring service, etc.
// await db.logs.insert(log);
// await monitoring.track(log);
});
res.json({ ok: true });
});
*/
// Standalone example for testing:
import express from 'express';
import cors from 'cors';
const app = express();
const PORT = 3001;
app.use(cors());
app.use(express.json());
app.post('/api/log', (req, res) => {
const logs = Array.isArray(req.body) ? req.body : [req.body];
console.log('\n=== FRONTEND LOGS RECEIVED ===');
logs.forEach(log => {
const timestamp = new Date(log.ts).toLocaleString();
const event = log.event.padEnd(30);
const route = log.context?.route || 'N/A';
const data = JSON.stringify(log.data || {}, null, 2);
console.log(`
┌─────────────────────────────────────────────────────────────
│ Event: ${log.event}
│ Time: ${timestamp}
│ Session: ${log.sessionId}
│ Route: ${route}
│ Theme: ${log.context?.theme || 'N/A'}
│ Data: ${data}
└─────────────────────────────────────────────────────────────
`);
});
res.json({ ok: true });
});
app.listen(PORT, () => {
console.log(`
╔════════════════════════════════════════════════════════════╗
║ Frontend Logging Test Server ║
║ Listening on http://localhost:${PORT} ║
║ ║
║ Endpoint: POST /api/log ║
║ ║
║ Configure ObsiViewer to use: ║
║ endpoint: 'http://localhost:${PORT}/api/log' ║
╚════════════════════════════════════════════════════════════╝
`);
});
// Graceful shutdown
process.on('SIGINT', () => {
console.log('\n\nShutting down logging server...');
process.exit(0);
});