v0.7.34 - We seemed to maybe finally fixed the monitoring error?
This commit is contained in:
391
api/index.js
391
api/index.js
@@ -23,6 +23,7 @@ let currentConfig = null;
|
||||
let relayPool = null;
|
||||
let subscriptionId = null;
|
||||
let isSubscribed = false; // Flag to prevent multiple simultaneous subscriptions
|
||||
let isSubscribing = false; // Flag to prevent re-entry during subscription setup
|
||||
// Relay connection state
|
||||
let relayInfo = null;
|
||||
let isRelayConnected = false;
|
||||
@@ -307,6 +308,13 @@ async function restoreAuthenticationState(pubkey) {
|
||||
|
||||
// Automatically set up relay connection based on current page URL
|
||||
async function setupAutomaticRelayConnection(showSections = false) {
|
||||
console.log('=== SETUP AUTOMATIC RELAY CONNECTION CALLED ===');
|
||||
console.log('Call stack:', new Error().stack);
|
||||
console.log('showSections:', showSections);
|
||||
console.log('Current isRelayConnected:', isRelayConnected);
|
||||
console.log('Current relayPool:', relayPool ? 'EXISTS' : 'NULL');
|
||||
console.log('Current isSubscribed:', isSubscribed);
|
||||
|
||||
try {
|
||||
// Get the current page URL and convert to WebSocket URL
|
||||
const currentUrl = window.location.href;
|
||||
@@ -322,8 +330,9 @@ async function setupAutomaticRelayConnection(showSections = false) {
|
||||
}
|
||||
|
||||
// Remove any path components to get just the base URL
|
||||
// CRITICAL: Always add trailing slash for consistent URL format
|
||||
const url = new URL(relayUrl);
|
||||
relayUrl = `${url.protocol}//${url.host}`;
|
||||
relayUrl = `${url.protocol}//${url.host}/`;
|
||||
|
||||
// Set the relay URL
|
||||
relayConnectionUrl.value = relayUrl;
|
||||
@@ -348,13 +357,8 @@ async function setupAutomaticRelayConnection(showSections = false) {
|
||||
relayPubkey = '4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa';
|
||||
}
|
||||
|
||||
// Initialize relay pool for admin API communication
|
||||
if (!relayPool) {
|
||||
relayPool = new window.NostrTools.SimplePool();
|
||||
console.log('🔌 Initialized SimplePool for admin API communication');
|
||||
}
|
||||
|
||||
// Set up subscription to receive admin API responses
|
||||
// Note: subscribeToConfiguration() will create the SimplePool internally
|
||||
await subscribeToConfiguration();
|
||||
console.log('📡 Subscription established for admin API responses');
|
||||
|
||||
@@ -615,16 +619,22 @@ async function loadUserProfile() {
|
||||
'wss://relay.nostr.band',
|
||||
'wss://nos.lol',
|
||||
'wss://relay.primal.net',
|
||||
'wss://relay.snort.social',
|
||||
'wss://relay.laantungir.net'];
|
||||
'wss://relay.snort.social'
|
||||
];
|
||||
|
||||
// Get profile event (kind 0) for the user
|
||||
const events = await profilePool.querySync(relays, {
|
||||
// Get profile event (kind 0) for the user with timeout
|
||||
const timeoutPromise = new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error('Profile query timeout')), 5000)
|
||||
);
|
||||
|
||||
const queryPromise = profilePool.querySync(relays, {
|
||||
kinds: [0],
|
||||
authors: [userPubkey],
|
||||
limit: 1
|
||||
});
|
||||
|
||||
const events = await Promise.race([queryPromise, timeoutPromise]);
|
||||
|
||||
if (events.length > 0) {
|
||||
console.log('Profile event found:', events[0]);
|
||||
const profile = JSON.parse(events[0].content);
|
||||
@@ -648,8 +658,14 @@ async function loadUserProfile() {
|
||||
// Keep the npub display
|
||||
}
|
||||
|
||||
// Close the profile pool
|
||||
profilePool.close(relays);
|
||||
// Properly close the profile pool with error handling
|
||||
try {
|
||||
await profilePool.close(relays);
|
||||
// Give time for cleanup
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
} catch (closeError) {
|
||||
console.log('Profile pool close error (non-critical):', closeError.message);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('Profile loading failed: ' + error.message);
|
||||
@@ -755,20 +771,25 @@ async function logout() {
|
||||
// Stop auto-refresh before disconnecting
|
||||
stopStatsAutoRefresh();
|
||||
|
||||
|
||||
// Clean up configuration pool
|
||||
// Clean up relay pool
|
||||
if (relayPool) {
|
||||
log('Closing configuration pool...', 'INFO');
|
||||
log('Closing relay pool...', 'INFO');
|
||||
const url = relayConnectionUrl.value.trim();
|
||||
if (url) {
|
||||
relayPool.close([url]);
|
||||
try {
|
||||
await relayPool.close([url]);
|
||||
} catch (e) {
|
||||
console.log('Pool close error (non-critical):', e.message);
|
||||
}
|
||||
}
|
||||
relayPool = null;
|
||||
subscriptionId = null;
|
||||
// Reset subscription flag
|
||||
isSubscribed = false;
|
||||
}
|
||||
|
||||
// Reset subscription flags
|
||||
isSubscribed = false;
|
||||
isSubscribing = false;
|
||||
|
||||
await nlLite.logout();
|
||||
|
||||
userPubkey = null;
|
||||
@@ -778,12 +799,9 @@ async function logout() {
|
||||
// Reset relay connection state
|
||||
isRelayConnected = false;
|
||||
relayPubkey = null;
|
||||
// Reset subscription flag
|
||||
isSubscribed = false;
|
||||
|
||||
// Reset UI - hide profile and show login modal
|
||||
hideProfileFromHeader();
|
||||
// showLoginModal() removed - handled by handleLogoutEvent()
|
||||
|
||||
updateConfigStatus(false);
|
||||
updateAdminSectionsVisibility();
|
||||
@@ -815,42 +833,204 @@ function generateSubId() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// WebSocket monitoring function to attach to SimplePool connections
|
||||
function attachWebSocketMonitoring(relayPool, url) {
|
||||
console.log('🔍 Attaching WebSocket monitoring to SimplePool...');
|
||||
|
||||
// SimplePool stores connections in _conn object
|
||||
if (relayPool && relayPool._conn) {
|
||||
// Monitor when connections are created
|
||||
const originalGetConnection = relayPool._conn[url];
|
||||
if (originalGetConnection) {
|
||||
console.log('📡 Found existing connection for URL:', url);
|
||||
|
||||
// Try to access the WebSocket if it's available
|
||||
const conn = relayPool._conn[url];
|
||||
if (conn && conn.ws) {
|
||||
attachWebSocketEventListeners(conn.ws, url);
|
||||
}
|
||||
}
|
||||
|
||||
// Override the connection getter to monitor new connections
|
||||
const originalConn = relayPool._conn;
|
||||
relayPool._conn = new Proxy(originalConn, {
|
||||
get(target, prop) {
|
||||
const conn = target[prop];
|
||||
if (conn && conn.ws && !conn.ws._monitored) {
|
||||
console.log('🔗 New WebSocket connection detected for:', prop);
|
||||
attachWebSocketEventListeners(conn.ws, prop);
|
||||
conn.ws._monitored = true;
|
||||
}
|
||||
return conn;
|
||||
},
|
||||
set(target, prop, value) {
|
||||
if (value && value.ws && !value.ws._monitored) {
|
||||
console.log('🔗 WebSocket connection being set for:', prop);
|
||||
attachWebSocketEventListeners(value.ws, prop);
|
||||
value.ws._monitored = true;
|
||||
}
|
||||
target[prop] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('✅ WebSocket monitoring attached');
|
||||
}
|
||||
|
||||
function attachWebSocketEventListeners(ws, url) {
|
||||
console.log(`🎯 Attaching event listeners to WebSocket for ${url}`);
|
||||
|
||||
// Log connection open
|
||||
ws.addEventListener('open', (event) => {
|
||||
console.log(`🔓 WebSocket OPEN for ${url}:`, {
|
||||
readyState: ws.readyState,
|
||||
url: ws.url,
|
||||
protocol: ws.protocol,
|
||||
extensions: ws.extensions
|
||||
});
|
||||
});
|
||||
|
||||
// Log incoming messages with full details
|
||||
ws.addEventListener('message', (event) => {
|
||||
try {
|
||||
const data = event.data;
|
||||
console.log(`📨 WebSocket MESSAGE from ${url}:`, {
|
||||
type: event.type,
|
||||
data: data,
|
||||
dataLength: data.length,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Try to parse as JSON for Nostr messages
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
if (Array.isArray(parsed)) {
|
||||
const [type, ...args] = parsed;
|
||||
console.log(`📨 Parsed Nostr message [${type}]:`, args);
|
||||
} else {
|
||||
console.log(`📨 Parsed JSON:`, parsed);
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.log(`📨 Raw message (not JSON):`, data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Error processing WebSocket message from ${url}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
// Log connection close with details
|
||||
ws.addEventListener('close', (event) => {
|
||||
console.log(`🔒 WebSocket CLOSE for ${url}:`, {
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
wasClean: event.wasClean,
|
||||
readyState: ws.readyState,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
// Log errors with full details
|
||||
ws.addEventListener('error', (event) => {
|
||||
console.error(`❌ WebSocket ERROR for ${url}:`, {
|
||||
type: event.type,
|
||||
target: event.target,
|
||||
readyState: ws.readyState,
|
||||
url: ws.url,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Log additional WebSocket state
|
||||
console.error(`❌ WebSocket state details:`, {
|
||||
readyState: ws.readyState,
|
||||
bufferedAmount: ws.bufferedAmount,
|
||||
protocol: ws.protocol,
|
||||
extensions: ws.extensions,
|
||||
binaryType: ws.binaryType
|
||||
});
|
||||
});
|
||||
|
||||
// Override send method to log outgoing messages
|
||||
const originalSend = ws.send;
|
||||
ws.send = function(data) {
|
||||
console.log(`📤 WebSocket SEND to ${url}:`, {
|
||||
data: data,
|
||||
dataLength: data.length,
|
||||
readyState: ws.readyState,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Try to parse outgoing Nostr messages
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
if (Array.isArray(parsed)) {
|
||||
const [type, ...args] = parsed;
|
||||
console.log(`📤 Outgoing Nostr message [${type}]:`, args);
|
||||
} else {
|
||||
console.log(`📤 Outgoing JSON:`, parsed);
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.log(`📤 Outgoing raw message (not JSON):`, data);
|
||||
}
|
||||
|
||||
return originalSend.call(this, data);
|
||||
};
|
||||
|
||||
console.log(`✅ Event listeners attached to WebSocket for ${url}`);
|
||||
}
|
||||
|
||||
// Configuration subscription using nostr-tools SimplePool
|
||||
async function subscribeToConfiguration() {
|
||||
try {
|
||||
console.log('=== STARTING SIMPLEPOOL CONFIGURATION SUBSCRIPTION ===');
|
||||
console.log('=== SUBSCRIBE TO CONFIGURATION ===');
|
||||
console.log('Call stack:', new Error().stack);
|
||||
|
||||
// Prevent multiple simultaneous subscription attempts
|
||||
if (isSubscribed) {
|
||||
console.log('Subscription already established, skipping duplicate subscription attempt');
|
||||
// If pool already exists and subscribed, we're done
|
||||
if (relayPool && isSubscribed) {
|
||||
console.log('✅ Already subscribed, reusing existing pool');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isLoggedIn) {
|
||||
console.log('WARNING: Not logged in, but proceeding with subscription test');
|
||||
}
|
||||
|
||||
const url = relayConnectionUrl.value.trim();
|
||||
if (!url) {
|
||||
console.error('Please enter a relay URL');
|
||||
// Prevent concurrent subscription attempts
|
||||
if (isSubscribing) {
|
||||
console.log('⚠️ Subscription already in progress');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`Connecting to relay via SimplePool: ${url}`);
|
||||
isSubscribing = true;
|
||||
|
||||
// Reuse existing pool if available, otherwise create new one
|
||||
const url = relayConnectionUrl.value.trim();
|
||||
if (!url) {
|
||||
console.error('No relay URL configured');
|
||||
isSubscribing = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`🔌 Connecting to relay: ${url}`);
|
||||
|
||||
// Create pool ONLY if it doesn't exist
|
||||
if (!relayPool) {
|
||||
console.log('Creating new SimplePool instance');
|
||||
console.log('✨ Creating NEW SimplePool for admin operations');
|
||||
relayPool = new window.NostrTools.SimplePool();
|
||||
|
||||
// Attach WebSocket monitoring to the new pool
|
||||
attachWebSocketMonitoring(relayPool, url);
|
||||
} else {
|
||||
console.log('Reusing existing SimplePool instance');
|
||||
console.log('♻️ Reusing existing SimplePool');
|
||||
}
|
||||
|
||||
subscriptionId = generateSubId();
|
||||
|
||||
console.log(`Generated subscription ID: ${subscriptionId}`);
|
||||
console.log(`User pubkey ${userPubkey}`)
|
||||
console.log(`📝 Generated subscription ID: ${subscriptionId}`);
|
||||
console.log(`👤 User pubkey: ${userPubkey}`);
|
||||
console.log(`🎯 About to call relayPool.subscribeMany with URL: ${url}`);
|
||||
console.log(`📊 relayPool._conn before subscribeMany:`, Object.keys(relayPool._conn || {}));
|
||||
|
||||
// Mark as subscribed BEFORE calling subscribeMany to prevent race conditions
|
||||
isSubscribed = true;
|
||||
|
||||
// Subscribe to kind 23457 events (admin response events), kind 4 (NIP-04 DMs), kind 1059 (NIP-17 GiftWrap), and kind 24567 (ephemeral monitoring events)
|
||||
console.log('🔔 Calling relayPool.subscribeMany...');
|
||||
const subscription = relayPool.subscribeMany([url], [{
|
||||
since: Math.floor(Date.now() / 1000) - 5, // Look back 5 seconds to avoid race condition
|
||||
kinds: [23457],
|
||||
@@ -872,20 +1052,21 @@ async function subscribeToConfiguration() {
|
||||
since: Math.floor(Date.now() / 1000), // Start from current time
|
||||
kinds: [24567], // Real-time ephemeral monitoring events
|
||||
authors: [getRelayPubkey()], // Only listen to monitoring events from the relay
|
||||
"#d": isLoggedIn ? ["event_kinds", "time_stats", "top_pubkeys", "active_subscriptions", "subscription_details"] : ["event_kinds", "time_stats", "top_pubkeys", "active_subscriptions"], // Include subscription_details only when authenticated
|
||||
"#d": isLoggedIn ? ["event_kinds", "time_stats", "top_pubkeys", "active_subscriptions", "subscription_details", "cpu_metrics"] : ["event_kinds", "time_stats", "top_pubkeys", "active_subscriptions", "cpu_metrics"], // Include subscription_details only when authenticated, cpu_metrics available to all
|
||||
limit: 50
|
||||
}], {
|
||||
async onevent(event) {
|
||||
console.log('=== EVENT RECEIVED VIA SIMPLEPOOL ===');
|
||||
console.log('Event data:', event);
|
||||
console.log('Event kind:', event.kind);
|
||||
console.log('Event tags:', event.tags);
|
||||
console.log('Event pubkey:', event.pubkey);
|
||||
console.log('=== END EVENT ===');
|
||||
// Simplified logging - one line per event
|
||||
if (event.kind === 24567) {
|
||||
const dTag = event.tags.find(tag => tag[0] === 'd');
|
||||
const dataType = dTag ? dTag[1] : 'unknown';
|
||||
console.log(`📊 Monitoring event: ${dataType}`);
|
||||
} else {
|
||||
console.log(`📨 Event received: kind ${event.kind}`);
|
||||
}
|
||||
|
||||
// Handle NIP-04 DMs
|
||||
if (event.kind === 4) {
|
||||
console.log('=== NIP-04 DM RECEIVED ===');
|
||||
try {
|
||||
// Decrypt the DM content
|
||||
const decryptedContent = await window.nostr.nip04.decrypt(event.pubkey, event.content);
|
||||
@@ -910,7 +1091,6 @@ async function subscribeToConfiguration() {
|
||||
|
||||
// Handle NIP-17 GiftWrap DMs
|
||||
if (event.kind === 1059) {
|
||||
console.log('=== NIP-17 GIFTWRAP RECEIVED ===');
|
||||
try {
|
||||
// Step 1: Unwrap gift wrap to get seal
|
||||
const sealJson = await window.nostr.nip44.decrypt(event.pubkey, event.content);
|
||||
@@ -958,10 +1138,7 @@ async function subscribeToConfiguration() {
|
||||
|
||||
// Handle monitoring events (kind 24567 - ephemeral)
|
||||
if (event.kind === 24567) {
|
||||
console.log('=== MONITORING EVENT RECEIVED ===');
|
||||
console.log('Monitoring event:', event);
|
||||
|
||||
// Process monitoring event
|
||||
// Process monitoring event (logging done above)
|
||||
processMonitoringEvent(event);
|
||||
}
|
||||
},
|
||||
@@ -975,23 +1152,30 @@ async function subscribeToConfiguration() {
|
||||
},
|
||||
onclose(reason) {
|
||||
console.log('Subscription closed:', reason);
|
||||
// Reset subscription state to allow re-subscription
|
||||
isSubscribed = false;
|
||||
isSubscribing = false;
|
||||
isRelayConnected = false;
|
||||
updateConfigStatus(false);
|
||||
log('WebSocket connection closed - subscription state reset', 'WARNING');
|
||||
}
|
||||
});
|
||||
|
||||
// Store subscription for cleanup
|
||||
relayPool.currentSubscription = subscription;
|
||||
|
||||
// Mark as subscribed to prevent duplicate attempts
|
||||
// Mark as subscribed
|
||||
isSubscribed = true;
|
||||
isSubscribing = false;
|
||||
|
||||
console.log('SimplePool subscription established');
|
||||
console.log('✅ Subscription established successfully');
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Configuration subscription failed:', error.message);
|
||||
console.error('Configuration subscription failed:', error);
|
||||
console.error('Error stack:', error.stack);
|
||||
isSubscribing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1087,13 +1271,14 @@ function initializeEventRateChart() {
|
||||
eventRateChart = new ASCIIBarChart('event-rate-chart', {
|
||||
maxHeight: 11, // Chart height in lines
|
||||
maxDataPoints: 76, // Show last 76 bins (5+ minutes of history)
|
||||
title: 'Events', // Chart title
|
||||
title: 'New Events', // Chart title
|
||||
xAxisLabel: '', // No X-axis label
|
||||
yAxisLabel: '', // No Y-axis label
|
||||
autoFitWidth: true, // Enable responsive font sizing
|
||||
useBinMode: true, // Enable time bin aggregation
|
||||
binDuration: 4000, // 4-second time bins
|
||||
xAxisLabelFormat: 'elapsed' // Show elapsed time labels
|
||||
xAxisLabelFormat: 'elapsed', // Show elapsed time labels
|
||||
debug: false // Disable debug logging
|
||||
});
|
||||
|
||||
console.log('ASCIIBarChart instance created:', eventRateChart);
|
||||
@@ -1148,70 +1333,56 @@ function createChartStubElements() {
|
||||
// Handle monitoring events (kind 24567 - ephemeral)
|
||||
async function processMonitoringEvent(event) {
|
||||
try {
|
||||
console.log('=== PROCESSING MONITORING EVENT ===');
|
||||
console.log('Monitoring event:', event);
|
||||
|
||||
// Verify this is a kind 24567 ephemeral monitoring event
|
||||
if (event.kind !== 24567) {
|
||||
console.log('Ignoring non-monitoring event, kind:', event.kind);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the event is from the relay
|
||||
const expectedRelayPubkey = getRelayPubkey();
|
||||
if (event.pubkey !== expectedRelayPubkey) {
|
||||
console.log('Ignoring monitoring event from unknown pubkey:', event.pubkey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the d-tag to determine which type of monitoring event this is
|
||||
const dTag = event.tags.find(tag => tag[0] === 'd');
|
||||
if (!dTag) {
|
||||
console.log('Ignoring monitoring event without d-tag');
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the monitoring data (content is JSON, not encrypted for monitoring events)
|
||||
const monitoringData = JSON.parse(event.content);
|
||||
console.log('Parsed monitoring data:', monitoringData);
|
||||
|
||||
// Don't add to chart here - we'll track actual event rate changes in updateStatsFromMonitoringEvent
|
||||
console.log('Monitoring event received - will track rate changes in stats update');
|
||||
|
||||
// Route to appropriate handler based on d-tag
|
||||
// Route to appropriate handler based on d-tag (no verbose logging)
|
||||
switch (dTag[1]) {
|
||||
case 'event_kinds':
|
||||
updateStatsFromMonitoringEvent(monitoringData);
|
||||
log('Real-time event_kinds monitoring data updated', 'INFO');
|
||||
break;
|
||||
|
||||
case 'time_stats':
|
||||
updateStatsFromTimeMonitoringEvent(monitoringData);
|
||||
log('Real-time time_stats monitoring data updated', 'INFO');
|
||||
break;
|
||||
|
||||
case 'top_pubkeys':
|
||||
updateStatsFromTopPubkeysMonitoringEvent(monitoringData);
|
||||
log('Real-time top_pubkeys monitoring data updated', 'INFO');
|
||||
break;
|
||||
|
||||
case 'active_subscriptions':
|
||||
updateStatsFromActiveSubscriptionsMonitoringEvent(monitoringData);
|
||||
log('Real-time active_subscriptions monitoring data updated', 'INFO');
|
||||
break;
|
||||
|
||||
case 'subscription_details':
|
||||
// Only process subscription details if user is authenticated
|
||||
if (isLoggedIn) {
|
||||
updateStatsFromSubscriptionDetailsMonitoringEvent(monitoringData);
|
||||
log('Real-time subscription_details monitoring data updated', 'INFO');
|
||||
} else {
|
||||
console.log('Ignoring subscription_details monitoring event - user not authenticated');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'cpu_metrics':
|
||||
updateStatsFromCpuMonitoringEvent(monitoringData);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Ignoring monitoring event with unknown d-tag:', dTag[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3770,11 +3941,8 @@ function handleStatsQueryResponse(responseData) {
|
||||
// Update statistics display from real-time monitoring event
|
||||
function updateStatsFromMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
log('Updating stats from monitoring event...', 'INFO');
|
||||
console.log('Monitoring data:', monitoringData);
|
||||
|
||||
if (monitoringData.data_type !== 'event_kinds') {
|
||||
log('Ignoring monitoring event with different data type', 'WARNING');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3801,8 +3969,6 @@ function updateStatsFromMonitoringEvent(monitoringData) {
|
||||
populateStatsKindsFromMonitoring(monitoringData.kinds, monitoringData.total_events);
|
||||
}
|
||||
|
||||
log('Real-time statistics updated from monitoring event', 'INFO');
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating stats from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
@@ -3811,11 +3977,7 @@ function updateStatsFromMonitoringEvent(monitoringData) {
|
||||
// Update statistics display from time_stats monitoring event
|
||||
function updateStatsFromTimeMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
log('Updating time stats from monitoring event...', 'INFO');
|
||||
console.log('Time monitoring data:', monitoringData);
|
||||
|
||||
if (monitoringData.data_type !== 'time_stats') {
|
||||
log('Ignoring time monitoring event with different data type', 'WARNING');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3834,8 +3996,6 @@ function updateStatsFromTimeMonitoringEvent(monitoringData) {
|
||||
populateStatsTime({ time_stats: timeStats });
|
||||
}
|
||||
|
||||
log('Real-time time statistics updated from monitoring event', 'INFO');
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating time stats from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
@@ -3844,11 +4004,7 @@ function updateStatsFromTimeMonitoringEvent(monitoringData) {
|
||||
// Update statistics display from top_pubkeys monitoring event
|
||||
function updateStatsFromTopPubkeysMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
log('Updating top pubkeys from monitoring event...', 'INFO');
|
||||
console.log('Top pubkeys monitoring data:', monitoringData);
|
||||
|
||||
if (monitoringData.data_type !== 'top_pubkeys') {
|
||||
log('Ignoring top pubkeys monitoring event with different data type', 'WARNING');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3858,8 +4014,6 @@ function updateStatsFromTopPubkeysMonitoringEvent(monitoringData) {
|
||||
populateStatsPubkeysFromMonitoring(monitoringData.pubkeys, monitoringData.total_events || 0);
|
||||
}
|
||||
|
||||
log('Real-time top pubkeys statistics updated from monitoring event', 'INFO');
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating top pubkeys from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
@@ -3868,11 +4022,7 @@ function updateStatsFromTopPubkeysMonitoringEvent(monitoringData) {
|
||||
// Update statistics display from active_subscriptions monitoring event
|
||||
function updateStatsFromActiveSubscriptionsMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
log('Updating active subscriptions from monitoring event...', 'INFO');
|
||||
console.log('Active subscriptions monitoring data:', monitoringData);
|
||||
|
||||
if (monitoringData.data_type !== 'active_subscriptions') {
|
||||
log('Ignoring active subscriptions monitoring event with different data type', 'WARNING');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3882,8 +4032,6 @@ function updateStatsFromActiveSubscriptionsMonitoringEvent(monitoringData) {
|
||||
updateStatsCell('active-subscriptions', monitoringData.data.total_subscriptions.toString());
|
||||
}
|
||||
|
||||
log('Real-time active subscriptions statistics updated from monitoring event', 'INFO');
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating active subscriptions from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
@@ -3892,11 +4040,7 @@ function updateStatsFromActiveSubscriptionsMonitoringEvent(monitoringData) {
|
||||
// Update statistics display from subscription_details monitoring event
|
||||
function updateStatsFromSubscriptionDetailsMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
log('Updating subscription details from monitoring event...', 'INFO');
|
||||
console.log('Subscription details monitoring data:', monitoringData);
|
||||
|
||||
if (monitoringData.data_type !== 'subscription_details') {
|
||||
log('Ignoring subscription details monitoring event with different data type', 'WARNING');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3905,13 +4049,43 @@ function updateStatsFromSubscriptionDetailsMonitoringEvent(monitoringData) {
|
||||
populateSubscriptionDetailsTable(monitoringData.data.subscriptions);
|
||||
}
|
||||
|
||||
log('Real-time subscription details statistics updated from monitoring event', 'INFO');
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating subscription details from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
// Update statistics display from CPU metrics monitoring event
|
||||
function updateStatsFromCpuMonitoringEvent(monitoringData) {
|
||||
try {
|
||||
if (monitoringData.data_type !== 'cpu_metrics') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update CPU metrics in the database statistics table
|
||||
if (monitoringData.process_id !== undefined) {
|
||||
updateStatsCell('process-id', monitoringData.process_id.toString());
|
||||
}
|
||||
|
||||
if (monitoringData.memory_usage_mb !== undefined) {
|
||||
updateStatsCell('memory-usage', monitoringData.memory_usage_mb.toFixed(1) + ' MB');
|
||||
}
|
||||
|
||||
if (monitoringData.current_cpu_core !== undefined) {
|
||||
updateStatsCell('cpu-core', 'Core ' + monitoringData.current_cpu_core);
|
||||
}
|
||||
|
||||
// Calculate CPU usage percentage if we have the data
|
||||
if (monitoringData.process_cpu_time !== undefined && monitoringData.system_cpu_time !== undefined) {
|
||||
// For now, just show the raw process CPU time (simplified)
|
||||
// In a real implementation, you'd calculate deltas over time
|
||||
updateStatsCell('cpu-usage', monitoringData.process_cpu_time + ' ticks');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(`Error updating CPU metrics from monitoring event: ${error.message}`, 'ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
// Populate event kinds table from monitoring data
|
||||
function populateStatsKindsFromMonitoring(kindsData, totalEvents) {
|
||||
const tableBody = document.getElementById('stats-kinds-table-body');
|
||||
@@ -4076,7 +4250,7 @@ function populateSubscriptionDetailsTable(subscriptionsData) {
|
||||
|
||||
if (subscriptionsData.length === 0) {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = '<td colspan="6" style="text-align: center; font-style: italic;">No active subscriptions</td>';
|
||||
row.innerHTML = '<td colspan="5" style="text-align: center; font-style: italic;">No active subscriptions</td>';
|
||||
tableBody.appendChild(row);
|
||||
return;
|
||||
}
|
||||
@@ -4092,8 +4266,8 @@ function populateSubscriptionDetailsTable(subscriptionsData) {
|
||||
// Format client IP (show full IP for admin view)
|
||||
const clientIP = subscription.client_ip || 'unknown';
|
||||
|
||||
// Format status
|
||||
const status = subscription.active ? 'Active' : 'Inactive';
|
||||
// Format wsi_pointer (show full pointer)
|
||||
const wsiPointer = subscription.wsi_pointer || 'N/A';
|
||||
|
||||
// Format filters (show actual filter details)
|
||||
let filtersDisplay = 'None';
|
||||
@@ -4161,9 +4335,8 @@ function populateSubscriptionDetailsTable(subscriptionsData) {
|
||||
row.innerHTML = `
|
||||
<td style="font-family: 'Courier New', monospace; font-size: 12px;">${subscription.id || 'N/A'}</td>
|
||||
<td style="font-family: 'Courier New', monospace; font-size: 12px;">${clientIP}</td>
|
||||
<td style="font-family: 'Courier New', monospace; font-size: 12px;">${wsiPointer}</td>
|
||||
<td>${durationStr}</td>
|
||||
<td>${subscription.events_sent || 0}</td>
|
||||
<td>${status}</td>
|
||||
<td>${filtersDisplay}</td>
|
||||
`;
|
||||
tableBody.appendChild(row);
|
||||
|
||||
Reference in New Issue
Block a user