feat(monitoring): add server-side client logging and health infrastructure
- add Alembic migration c1d2e3f4g5h6 for client monitoring:
- create client_logs table with FK to clients.uuid and performance indexes
- extend clients with process/health tracking fields
- extend data model with ClientLog, LogLevel, ProcessStatus, and ScreenHealthStatus
- enhance listener MQTT handling:
- subscribe to logs and health topics
- persist client logs from infoscreen/{uuid}/logs/{level}
- process health payloads and enrich heartbeat-derived client state
- add monitoring API blueprint server/routes/client_logs.py:
- GET /api/client-logs/<uuid>/logs
- GET /api/client-logs/summary
- GET /api/client-logs/recent-errors
- GET /api/client-logs/test
- register client_logs blueprint in server/wsgi.py
- align compose/dev runtime for listener live-code execution
- add client-side implementation docs:
- CLIENT_MONITORING_SPECIFICATION.md
- CLIENT_MONITORING_IMPLEMENTATION_GUIDE.md
- update TECH-CHANGELOG.md and copilot-instructions.md:
- document monitoring changes
- codify post-release technical-notes/no-version-bump convention
This commit is contained in:
@@ -21,6 +21,27 @@ class AcademicPeriodType(enum.Enum):
|
||||
trimester = "trimester"
|
||||
|
||||
|
||||
class LogLevel(enum.Enum):
|
||||
ERROR = "ERROR"
|
||||
WARN = "WARN"
|
||||
INFO = "INFO"
|
||||
DEBUG = "DEBUG"
|
||||
|
||||
|
||||
class ProcessStatus(enum.Enum):
|
||||
running = "running"
|
||||
crashed = "crashed"
|
||||
starting = "starting"
|
||||
stopped = "stopped"
|
||||
|
||||
|
||||
class ScreenHealthStatus(enum.Enum):
|
||||
OK = "OK"
|
||||
BLACK = "BLACK"
|
||||
FROZEN = "FROZEN"
|
||||
UNKNOWN = "UNKNOWN"
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = 'users'
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
@@ -106,6 +127,31 @@ class Client(Base):
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
group_id = Column(Integer, ForeignKey(
|
||||
'client_groups.id'), nullable=False, default=1)
|
||||
|
||||
# Health monitoring fields
|
||||
current_event_id = Column(Integer, nullable=True)
|
||||
current_process = Column(String(50), nullable=True) # 'vlc', 'chromium', 'pdf_viewer'
|
||||
process_status = Column(Enum(ProcessStatus), nullable=True)
|
||||
process_pid = Column(Integer, nullable=True)
|
||||
last_screenshot_analyzed = Column(TIMESTAMP(timezone=True), nullable=True)
|
||||
screen_health_status = Column(Enum(ScreenHealthStatus), nullable=True, server_default='UNKNOWN')
|
||||
last_screenshot_hash = Column(String(32), nullable=True)
|
||||
|
||||
|
||||
class ClientLog(Base):
|
||||
__tablename__ = 'client_logs'
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
client_uuid = Column(String(36), ForeignKey('clients.uuid', ondelete='CASCADE'), nullable=False, index=True)
|
||||
timestamp = Column(TIMESTAMP(timezone=True), nullable=False, index=True)
|
||||
level = Column(Enum(LogLevel), nullable=False, index=True)
|
||||
message = Column(Text, nullable=False)
|
||||
context = Column(Text, nullable=True) # JSON stored as text
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.current_timestamp(), nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
Index('ix_client_logs_client_timestamp', 'client_uuid', 'timestamp'),
|
||||
Index('ix_client_logs_level_timestamp', 'level', 'timestamp'),
|
||||
)
|
||||
|
||||
|
||||
class EventType(enum.Enum):
|
||||
|
||||
Reference in New Issue
Block a user