From b268fb21967363694efc85da65854caac64bf16f Mon Sep 17 00:00:00 2001 From: LeeGordon83 Date: Mon, 19 Jan 2026 11:08:38 +0000 Subject: [PATCH] Add diagnostic logging and connectivity health check for CDP - Add detailed logging in flood-service.js for API calls and responses - Log API URLs, HTTP status codes, and error details - Add /health/connectivity endpoint to test external API reachability - Add request logging in station route handler - Will help diagnose 404 errors in CDP environment --- src/lib/flood-service.js | 18 +++++++++++---- src/plugins/router.js | 2 ++ src/routes/health-check.js | 47 ++++++++++++++++++++++++++++++++++++++ src/routes/station.js | 3 +++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/routes/health-check.js diff --git a/src/lib/flood-service.js b/src/lib/flood-service.js index 62c3896..98f1001 100644 --- a/src/lib/flood-service.js +++ b/src/lib/flood-service.js @@ -28,19 +28,25 @@ export function proxyFetch (url, options = {}) { * Fetch station details by RLOI ID (Check for Flooding ID) */ export async function getStation (stationId) { + const url = `${API_BASE_URL}/id/stations?RLOIid=${stationId}` try { - const response = await proxyFetch(`${API_BASE_URL}/id/stations?RLOIid=${stationId}`) + console.log(`Fetching station from: ${url}`) + const response = await proxyFetch(url) + console.log(`Station API response status: ${response.status} ${response.statusText}`) + if (!response.ok) { - throw new Error(`Failed to fetch station: ${response.statusText}`) + throw new Error(`Failed to fetch station: ${response.status} ${response.statusText}`) } const data = await response.json() // The API returns an array of stations in items if (data.items && data.items.length > 0) { + console.log(`Station data retrieved successfully for ${stationId}`) return data.items[0] } + console.log(`No station items found for ${stationId}`) return null } catch (error) { - console.error('Error fetching station:', error) + console.error(`Error fetching station from ${url}:`, error.message, error.cause) return null } } @@ -49,14 +55,18 @@ export async function getStation (stationId) { * Fetch station readings/measurements */ export async function getStationReadings (stationId, since = null) { + const stationUrl = `${API_BASE_URL}/id/stations?RLOIid=${stationId}` try { // First get the station to find its measures - const stationResponse = await proxyFetch(`${API_BASE_URL}/id/stations?RLOIid=${stationId}`) + console.log(`Fetching station for readings from: ${stationUrl}`) + const stationResponse = await proxyFetch(stationUrl) if (!stationResponse.ok) { + console.error(`Station fetch for readings failed: ${stationResponse.status} ${stationResponse.statusText}`) throw new Error('Station not found') } const stationData = await stationResponse.json() if (!stationData.items || stationData.items.length === 0) { + console.log(`No station items found for readings: ${stationId}`) return [] } diff --git a/src/plugins/router.js b/src/plugins/router.js index 61bf7b1..847e2be 100644 --- a/src/plugins/router.js +++ b/src/plugins/router.js @@ -1,5 +1,6 @@ import Inert from '@hapi/inert' import { health } from '../routes/health.js' +import { healthCheck } from '../routes/health-check.js' import { index } from '../routes/index.js' import { station } from '../routes/station.js' import { serveStaticFiles } from '../common/helpers/serve-static-files.js' @@ -10,6 +11,7 @@ export const router = { async register (server) { await server.register([Inert]) await server.route(health) + await server.route(healthCheck) await server.route(index) await server.route(station) await server.register([serveStaticFiles]) diff --git a/src/routes/health-check.js b/src/routes/health-check.js new file mode 100644 index 0000000..f1cd103 --- /dev/null +++ b/src/routes/health-check.js @@ -0,0 +1,47 @@ +/** + * Extended health check endpoint that also tests external API connectivity + */ +export const healthCheck = { + method: 'GET', + path: '/health/connectivity', + handler: async function (request, h) { + const results = { + service: 'ok', + timestamp: new Date().toISOString(), + externalApis: {} + } + + // Test Environment Agency API connectivity + try { + const testUrl = 'https://environment.data.gov.uk/flood-monitoring/id/stations?RLOIid=8085' + request.logger.info(`Testing connectivity to: ${testUrl}`) + + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), 5000) + + const response = await fetch(testUrl, { signal: controller.signal }) + clearTimeout(timeoutId) + + results.externalApis.environmentAgency = { + url: testUrl, + status: response.status, + statusText: response.statusText, + reachable: response.ok + } + + if (response.ok) { + const data = await response.json() + results.externalApis.environmentAgency.itemsCount = data.items?.length || 0 + } + } catch (error) { + request.logger.error('Environment Agency API connectivity test failed:', error) + results.externalApis.environmentAgency = { + reachable: false, + error: error.message, + errorType: error.name + } + } + + return h.response(results).code(200) + } +} diff --git a/src/routes/station.js b/src/routes/station.js index 5d7ef6b..364d0ef 100644 --- a/src/routes/station.js +++ b/src/routes/station.js @@ -7,6 +7,8 @@ export const station = { const { dataType, stationType, stationId = '8085' } = request.query try { + request.logger.info(`Fetching station data for ID: ${stationId}`) + // Fetch real data from Environment Agency API const [stationData, readings] = await Promise.all([ getStation(stationId), @@ -14,6 +16,7 @@ export const station = { ]) if (!stationData) { + request.logger.warn(`Station not found or API call failed for ID: ${stationId}`) return h.view('error.njk', { error: 'Station not found', message: `Could not find station with ID: ${stationId}`