Claude Code Claude Opus 4.6 commited on
Commit
230bdd7
·
1 Parent(s): dca87f5

Claude Code: add /debug/health endpoint with uptime, memory, status, and modules

Browse files

- Add GET /debug/health endpoint returning JSON status report
- Track application uptime from START_TIME
- Report memory usage (RSS and VMS) via psutil
- Include last 5 lines from cain_status.json
- List loaded Python modules (first 100)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +47 -0
app.py CHANGED
@@ -14,6 +14,9 @@ import sys
14
  from datetime import datetime
15
  import asyncio
16
  from contextlib import asynccontextmanager
 
 
 
17
 
18
  # Add /app to sys.path for proper package imports
19
  sys.path.insert(0, "/app")
@@ -23,6 +26,9 @@ from openclaw.core.system_logger import log_startup, log_heartbeat, get_last_lin
23
  # Import error handlers
24
  from error_handlers import handle_status_file_read, handle_brain_response, handle_websocket_send
25
 
 
 
 
26
 
27
  @asynccontextmanager
28
  async def lifespan(app: FastAPI):
@@ -172,6 +178,47 @@ async def admin_system():
172
  }
173
 
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  if __name__ == "__main__":
176
  import uvicorn
177
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
14
  from datetime import datetime
15
  import asyncio
16
  from contextlib import asynccontextmanager
17
+ import time
18
+ import json
19
+ import psutil
20
 
21
  # Add /app to sys.path for proper package imports
22
  sys.path.insert(0, "/app")
 
26
  # Import error handlers
27
  from error_handlers import handle_status_file_read, handle_brain_response, handle_websocket_send
28
 
29
+ # Track startup time for uptime calculation
30
+ START_TIME = time.time()
31
+
32
 
33
  @asynccontextmanager
34
  async def lifespan(app: FastAPI):
 
178
  }
179
 
180
 
181
+ @app.get("/debug/health")
182
+ async def debug_health():
183
+ """Debug health endpoint with detailed system status."""
184
+ # 1. Uptime in seconds
185
+ uptime = time.time() - START_TIME
186
+
187
+ # 2. Current memory usage of the current process (brain_minimal runs in same process)
188
+ process = psutil.Process(os.getpid())
189
+ memory_info = process.memory_info()
190
+ memory_mb = memory_info.rss / 1024 / 1024 # Convert to MB
191
+
192
+ # 3. Last 5 lines from cain_status.json (read as structured JSON)
193
+ cain_status_path = "/app/openclaw/.openclaw/agents/cain_status.json"
194
+ cain_status_lines = []
195
+ try:
196
+ if os.path.exists(cain_status_path):
197
+ with open(cain_status_path, "r") as f:
198
+ content = f.read()
199
+ lines = content.strip().split("\n")
200
+ cain_status_lines = lines[-5:] if len(lines) > 5 else lines
201
+ else:
202
+ cain_status_lines = ["cain_status.json not found"]
203
+ except Exception as e:
204
+ cain_status_lines = [f"Error reading cain_status.json: {str(e)}"]
205
+
206
+ # 4. List of loaded Python modules
207
+ loaded_modules = sorted([name for name in sys.modules.keys() if not name.startswith("_")])[:100]
208
+
209
+ return {
210
+ "uptime_seconds": round(uptime, 2),
211
+ "memory": {
212
+ "rss_mb": round(memory_mb, 2),
213
+ "vms_mb": round(memory_info.vms / 1024 / 1024, 2)
214
+ },
215
+ "cain_status_last_lines": cain_status_lines,
216
+ "loaded_modules_count": len(loaded_modules),
217
+ "loaded_modules": loaded_modules,
218
+ "timestamp": datetime.utcnow().isoformat() + "+00:00"
219
+ }
220
+
221
+
222
  if __name__ == "__main__":
223
  import uvicorn
224
  uvicorn.run(app, host="0.0.0.0", port=7860)