diff --git a/modules/analyze.js b/modules/analyze.js index 8ecc69b..df5ee02 100644 --- a/modules/analyze.js +++ b/modules/analyze.js @@ -19,41 +19,45 @@ function analyzeURL(req, res) { } const hostname = url.parse(urlToAnalyze).hostname; - const options = { - method: 'HEAD', - timeout: 5000, - }; - - const start = now(); - - makeHttpRequest(urlToAnalyze, options, (response, httpRequestError) => { - if (httpRequestError) { - console.error(`Failed to request ${urlToAnalyze}: ${httpRequestError}`); - return res.json({ isUp: false, ipAddress: null, uptime: 0, responseTime: 0 }); + makeHttpRequest(urlToAnalyze, {}, (responseDetails, latencyMs, httpRequestError) => { + if (httpRequestError || !responseDetails) { + console.error(`Failed to request ${urlToAnalyze}: ${httpRequestError || 'Unknown error'}`); + return res.json({ isUp: false, ipAddress: null, uptime: 0, latencyMs: 0, dnsLookupMs: 0 }); } - const isUp = response.statusCode >= 200 && response.statusCode < 400; + const isUp = + responseDetails.statusCode >= 200 && responseDetails.statusCode < 400; if (!isUp) { - return res.json({ isUp: false, ipAddress: null, uptime: 0, responseTime: 0 }); + return res.json({ + isUp: false, + ipAddress: null, + uptime: 0, + latencyMs, + dnsLookupMs: 0, + statusCode: responseDetails.statusCode, + }); } - performDnsLookup(hostname, (ipAddress, dnsLookupError) => { + performDnsLookup(hostname, ({ ipAddress, lookupMs, error: dnsLookupError }) => { if (dnsLookupError) { console.error(`Failed to lookup IP address for ${urlToAnalyze}: ${dnsLookupError}`); return res.status(500).json({ error: 'Internal server error' }); } - // Calculate responseTime - const end = now(); - const responseTime = ((end - start) / 1000).toFixed(2); - - // calculate uptime - const totalSeconds = (end - start) / 1000; // convert to seconds - const availableSeconds = totalSeconds - (totalSeconds * 0.01); // assuming 99.99% uptime - const uptime = ((availableSeconds / totalSeconds) * 100).toFixed(2); + // Calculate uptime baseline on successful check + const uptime = 100; - console.log(`isUp: ${isUp}, ipAddress: ${ipAddress}, uptime: ${uptime}%, responseTime: ${responseTime}s`); - return res.json({ isUp: true, ipAddress, uptime, responseTime }); + console.log( + `isUp: ${isUp}, ipAddress: ${ipAddress}, uptime: ${uptime}%, latencyMs: ${latencyMs}, dnsLookupMs: ${lookupMs}` + ); + return res.json({ + isUp: true, + ipAddress, + uptime, + latencyMs, + dnsLookupMs: lookupMs, + statusCode: responseDetails.statusCode, + }); }); }); } catch (error) { diff --git a/modules/dnsLookup.js b/modules/dnsLookup.js index 4c89f01..3cd266c 100644 --- a/modules/dnsLookup.js +++ b/modules/dnsLookup.js @@ -1,11 +1,14 @@ const dns = require('dns'); +const now = require('performance-now'); function performDnsLookup(hostname, callback) { + const start = now(); dns.lookup(hostname, (error, ipAddress) => { + const lookupMs = Number((now() - start).toFixed(2)); if (error) { - callback(null, error); + callback({ error, lookupMs }); } else { - callback(ipAddress); + callback({ ipAddress, lookupMs }); } }); } diff --git a/modules/httpRequest.js b/modules/httpRequest.js index ada8fdf..98530c1 100644 --- a/modules/httpRequest.js +++ b/modules/httpRequest.js @@ -1,15 +1,38 @@ const http = require('http'); const https = require('https'); +const now = require('performance-now'); -function makeHttpRequest(urlToAnalyze, options, callback) { +function makeHttpRequest(urlToAnalyze, options = {}, callback) { const protocol = urlToAnalyze.startsWith('https://') ? https : http; + const requestOptions = { + method: 'GET', + timeout: 8000, + ...options, + }; - const request = protocol.request(urlToAnalyze, options, (response) => { - callback(response); + const start = now(); + const request = protocol.request(urlToAnalyze, requestOptions, (response) => { + // consume the response to ensure the 'end' event fires for timing accuracy + response.on('data', () => {}); + + response.on('end', () => { + const latencyMs = Number((now() - start).toFixed(2)); + callback( + { + statusCode: response.statusCode, + headers: response.headers, + }, + latencyMs + ); + }); + }); + + request.on('timeout', () => { + request.destroy(new Error('Request timed out')); }); request.on('error', (error) => { - callback(null, error); + callback(null, 0, error); }); request.end();