import json import threading from http.server import HTTPServer, BaseHTTPRequestHandler from datetime import datetime, timezone import logging from config import HEALTH_CHECK_PORT, HEALTH_CHECK_ENABLED class HealthCheckHandler(BaseHTTPRequestHandler): def do_GET(self): if self.path == '/health': self.send_health_response() elif self.path == '/sensors': self.send_sensors_status() else: self.send_response(404) self.end_headers() def send_health_response(self): """Send basic health check response""" health_data = { "status": "healthy", "timestamp": datetime.now(timezone.utc).isoformat(), "service": "modbus-mqtt-bridge", "version": "1.0.0" } self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(health_data, indent=2).encode()) def send_sensors_status(self): """Send detailed sensor status""" # Get sensor status from the global sensor tracker from sensor_tracker import get_all_sensor_status sensors_status = get_all_sensor_status() self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(sensors_status, indent=2).encode()) def log_message(self, format, *args): """Override to use our logging system""" logging.info(f"Health Check - {format % args}") class HealthCheckServer: def __init__(self, port=HEALTH_CHECK_PORT): self.port = port self.server = None self.thread = None def start(self): """Start the health check server in a separate thread""" if not HEALTH_CHECK_ENABLED: logging.info("Health check server is disabled") return try: # Bind to all interfaces to make it accessible from outside container self.server = HTTPServer(('0.0.0.0', self.port), HealthCheckHandler) self.thread = threading.Thread(target=self.server.serve_forever, daemon=True) self.thread.start() logging.info(f"Health check server started on 0.0.0.0:{self.port}") logging.info(f"Health check endpoints:") logging.info(f" - http://0.0.0.0:{self.port}/health") logging.info(f" - http://0.0.0.0:{self.port}/sensors") except Exception as e: logging.error(f"Failed to start health check server: {e}") raise e # Re-raise to make the issue visible def stop(self): """Stop the health check server""" if self.server: self.server.shutdown() self.server.server_close() logging.info("Health check server stopped")