error logging silencing

pull/16/head
accius 3 days ago
parent cdec554f7e
commit 0010afbbf9

@ -38,8 +38,8 @@ let consecutiveFailures = 0;
let lastFailureTime = 0;
let lastLogTime = 0;
const FAILURE_THRESHOLD = 3; // Open after 3 failures
const CIRCUIT_RESET_TIME = 2 * 60 * 1000; // 2 minutes before retry
const LOG_INTERVAL = 30000; // Only log every 30 seconds
const CIRCUIT_RESET_TIME = 5 * 60 * 1000; // 5 minutes before retry
const LOG_INTERVAL = 60000; // Only log every 60 seconds
function getCacheKey(params) {
// Round coordinates to 1 decimal place for better cache hits

@ -41,6 +41,26 @@ if (ITURHFPROP_URL) {
app.use(cors());
app.use(express.json());
// ============================================
// RATE-LIMITED LOGGING
// ============================================
// Prevents log spam when services are down
const errorLogState = {};
const ERROR_LOG_INTERVAL = 60000; // Only log same error once per minute
function logErrorOnce(category, message) {
const key = `${category}:${message}`;
const now = Date.now();
const lastLogged = errorLogState[key] || 0;
if (now - lastLogged >= ERROR_LOG_INTERVAL) {
errorLogState[key] = now;
console.error(`[${category}] ${message}`);
return true;
}
return false;
}
// Serve static files - use 'dist' in production (Vite build), 'public' in development
const staticDir = process.env.NODE_ENV === 'production'
? path.join(__dirname, 'dist')
@ -526,7 +546,7 @@ app.get('/api/dxcluster/spots', async (req, res) => {
} catch (error) {
clearTimeout(timeout);
if (error.name !== 'AbortError') {
console.error('[DX Cluster] HamQTH error:', error.message);
logErrorOnce('DX Cluster', `HamQTH: ${error.message}`);
}
}
return null;
@ -554,7 +574,7 @@ app.get('/api/dxcluster/spots', async (req, res) => {
} catch (error) {
clearTimeout(timeout);
if (error.name !== 'AbortError') {
console.error('[DX Cluster] DX Spider Proxy error:', error.message);
logErrorOnce('DX Cluster', `Proxy: ${error.message}`);
}
}
return null;
@ -679,9 +699,9 @@ app.get('/api/dxcluster/spots', async (req, res) => {
});
client.on('error', (err) => {
// Only log unexpected errors, not connection resets (they're common)
if (!err.message.includes('ECONNRESET') && !err.message.includes('ETIMEDOUT') && !err.message.includes('ENOTFOUND')) {
console.error(`[DX Cluster] DX Spider ${node.host} error:`, err.message);
// Only log unexpected errors, not connection issues (they're common)
if (!err.message.includes('ECONNRESET') && !err.message.includes('ETIMEDOUT') && !err.message.includes('ENOTFOUND') && !err.message.includes('ECONNREFUSED')) {
logErrorOnce('DX Cluster', `DX Spider ${node.host}: ${err.message}`);
}
cleanup();
});
@ -1542,7 +1562,7 @@ app.get('/api/myspots/:callsign', async (req, res) => {
res.json(spotsWithLocations);
} catch (error) {
console.error('[My Spots] Error:', error.message);
logErrorOnce('My Spots', error.message);
res.json([]);
}
});
@ -1770,7 +1790,7 @@ async function fetchIonosondeData() {
return validStations;
} catch (error) {
console.error('[Ionosonde] Fetch error:', error.message);
logErrorOnce('Ionosonde', `Fetch error: ${error.message}`);
return ionosondeCache.data || [];
}
}
@ -1785,7 +1805,7 @@ app.get('/api/ionosonde', async (req, res) => {
stations: stations
});
} catch (error) {
console.error('[Ionosonde] API error:', error.message);
logErrorOnce('Ionosonde', `API: ${error.message}`);
res.status(500).json({ error: 'Failed to fetch ionosonde data' });
}
});
@ -1923,12 +1943,12 @@ async function fetchITURHFPropPrediction(txLat, txLon, rxLat, rxLon, ssn, month,
clearTimeout(timeoutId);
if (!response.ok) {
console.log('[Hybrid] ITURHFProp returned error:', response.status, response.statusText);
logErrorOnce('Hybrid', `ITURHFProp returned ${response.status}`);
return null;
}
const data = await response.json();
console.log('[Hybrid] ITURHFProp prediction received, MUF:', data.muf);
// Only log success occasionally to reduce noise
// Cache the result
iturhfpropCache = {
@ -1940,7 +1960,9 @@ async function fetchITURHFPropPrediction(txLat, txLon, rxLat, rxLon, ssn, month,
return data;
} catch (err) {
console.log('[Hybrid] ITURHFProp service error:', err.name, err.message);
if (err.name !== 'AbortError') {
logErrorOnce('Hybrid', `ITURHFProp: ${err.message}`);
}
return null;
}
}
@ -1952,17 +1974,17 @@ async function fetchITURHFPropHourly(txLat, txLon, rxLat, rxLon, ssn, month) {
if (!ITURHFPROP_URL) return null;
try {
console.log('[Hybrid] Fetching 24-hour prediction from ITURHFProp...');
const url = `${ITURHFPROP_URL}/api/predict/hourly?txLat=${txLat}&txLon=${txLon}&rxLat=${rxLat}&rxLon=${rxLon}&ssn=${ssn}&month=${month}`;
const response = await fetch(url, { timeout: 60000 }); // 60s timeout for 24-hour calc
if (!response.ok) return null;
const data = await response.json();
console.log('[Hybrid] Received 24-hour prediction');
return data;
} catch (err) {
console.log('[Hybrid] ITURHFProp hourly unavailable:', err.message);
if (err.name !== 'AbortError') {
logErrorOnce('Hybrid', `ITURHFProp hourly: ${err.message}`);
}
return null;
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.