Files
POE-sensor/health_check.py

149 lines
5.3 KiB
Python

import json
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime, timezone
import logging
import time
import socket
import os
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"""
try:
# Try to get sensor status
try:
from sensor_tracker import get_sensor_tracker
sensor_tracker = get_sensor_tracker()
summary = sensor_tracker.get_summary()
health_data = {
"status": "healthy",
"timestamp": datetime.now(timezone.utc).isoformat(),
"service": "modbus-mqtt-bridge",
"version": "1.0.0",
"sensors": {
"total": summary.get('total_sensors', 0),
"online": summary.get('online_sensors', 0),
"health_percentage": summary.get('health_percentage', 0.0)
}
}
# Mark as degraded if no sensors online but service is running
if summary.get('total_sensors', 0) > 0 and summary.get('online_sensors', 0) == 0:
health_data["status"] = "degraded"
health_data["message"] = "All sensors offline"
except Exception as e:
# If sensor tracker not available, still report healthy
health_data = {
"status": "healthy",
"timestamp": datetime.now(timezone.utc).isoformat(),
"service": "modbus-mqtt-bridge",
"version": "1.0.0",
"message": "Service running, sensor status unavailable"
}
except Exception as e:
health_data = {
"status": "unhealthy",
"timestamp": datetime.now(timezone.utc).isoformat(),
"service": "modbus-mqtt-bridge",
"error": str(e)
}
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"""
try:
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())
except Exception as e:
error_response = {
"error": "Failed to get sensor status",
"message": str(e),
"timestamp": datetime.now(timezone.utc).isoformat()
}
self.send_response(500)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(error_response, indent=2).encode())
def log_message(self, format, *args):
"""Override to reduce noise"""
pass
class HealthCheckServer:
def __init__(self, port=None):
self.port = port or int(os.getenv('HEALTH_CHECK_PORT', HEALTH_CHECK_PORT))
self.server = None
self.thread = None
self.started = False
def start(self):
"""Start the health check server"""
if not HEALTH_CHECK_ENABLED:
logging.info("Health check server is disabled")
return False
try:
logging.info(f"Starting health check server on port {self.port}")
self.server = HTTPServer(('0.0.0.0', self.port), HealthCheckHandler)
self.thread = threading.Thread(target=self._serve, daemon=True)
self.thread.start()
# Give server time to start
time.sleep(1)
self.started = True
logging.info(f"Health check server running on http://0.0.0.0:{self.port}/health")
return True
except Exception as e:
logging.error(f"Failed to start health check server: {e}")
return False
def _serve(self):
"""Serve requests"""
try:
if self.server:
self.server.serve_forever()
except Exception as e:
logging.error(f"Health check server error: {e}")
self.started = False
def stop(self):
"""Stop the server"""
if self.server:
self.server.shutdown()
self.server.server_close()
self.started = False
logging.info("Health check server stopped")
def is_running(self):
"""Check if server is running"""
return self.started and self.thread and self.thread.is_alive()