Monitoring & Performance
Section titled “Monitoring & Performance”Monitor runtime health, inspect in-flight script requests, aggregate per-script metrics, scrape Prometheus-compatible metrics, and restart the exec server when needed. Use these endpoints to build dashboards, alerting, and operational tooling around the Hoody exec runtime.
All endpoints below are scoped to a specific project container and are served from the container-scoped subdomain pattern https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu. Replace {projectId}, {containerId}, and {server} with your values.
Health & Status
Section titled “Health & Status”GET /api/v1/exec/health
Section titled “GET /api/v1/exec/health”Lightweight liveness probe. Returns runtime metadata (build timestamp, start time, memory, PID, file descriptor count) without touching any heavy subsystems. Safe to call from load balancers and uptime monitors.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/health"const result = await client.exec.health.check();{ "status": "ok", "service": "hoody-exec", "built": "2026-01-15T10:24:18.000Z", "started": "2026-01-22T08:01:53.000Z", "memory": { "rss": 89456640, "heap": 27131904 }, "fds": 28, "pid": 4711, "ip": "10.0.4.18", "userAgent": "curl/8.5.0"}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}GET /api/v1/exec/system/restart-status
Section titled “GET /api/v1/exec/system/restart-status”Inspects whether the exec server can safely be restarted right now. Reports uptime, the count of in-flight requests, and whether each in-flight request is still active. Use this before calling POST /api/v1/exec/system/restart to decide between graceful and forced drains.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/system/restart-status"const status = await client.exec.system.getRestartStatus();{ "canRestart": true, "uptime": 3642.512, "uptimeFormatted": "1h 0m 42s", "activeRequests": 2, "active": [ { "executionId": "exec_01HMZ8XK4A2D8Q9R1F7VN6T3PB", "scriptPath": "/api/users/[id].js", "method": "GET", "url": "https://app.example.com/api/users/u_91827", "startedAt": "2026-01-22T08:00:12.184Z", "duration": 30184 } ], "restartReady": true}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}Active Requests
Section titled “Active Requests”GET /api/v1/exec/monitor/active-requests
Section titled “GET /api/v1/exec/monitor/active-requests”Returns every in-flight script HTTP request currently being handled by the exec server. Each entry includes the script path, method, URL (with the auth token redacted), and the elapsed duration in milliseconds. Useful for live debugging when requests appear to be stuck.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/monitor/active-requests"const active = await client.exec.monitor.getActiveRequests();{ "count": 2, "active": [ { "executionId": "exec_01HMZ8XK4A2D8Q9R1F7VN6T3PB", "scriptPath": "/api/users/[id].js", "hostname": "app.example.com", "clientIp": "203.0.113.42", "method": "GET", "url": "https://app.example.com/api/users/u_91827", "startedAt": "2026-01-22T08:00:12.184Z", "duration": 30184 }, { "executionId": "exec_01HMZ8XN9C5T7B2Q4K8WP6V3JD", "scriptPath": "/api/orders/checkout.js", "hostname": "app.example.com", "clientIp": "198.51.100.7", "method": "POST", "url": "https://app.example.com/api/orders/checkout", "startedAt": "2026-01-22T08:00:38.901Z", "duration": 2345 } ]}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}Aggregate Stats
Section titled “Aggregate Stats”GET /api/v1/exec/monitor/stats
Section titled “GET /api/v1/exec/monitor/stats”Returns lifetime runtime counters: uptime, memory usage, cache sizes, request totals with rolling averages (1m / 5m / 15m), WebSocket counters, and cron scheduler counters. Use this for top-level dashboards and alerting thresholds.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/monitor/stats"const stats = await client.exec.monitor.getStats();{ "uptime": 3642, "memory": { "used": 27131904, "total": 33554432, "percentage": 80.87, "rss": 89456640, "external": 1835008 }, "cache": { "scripts": 142, "vms": 18, "sharedStates": 9, "activeWsHostnames": 4 }, "requests": { "total": 128439, "success": 126118, "errors": 2321, "activeHttp": 2, "perSecond": 35.27, "per1m": 41.8, "per5m": 38.2, "per15m": 36.4 }, "websocket": { "opened": 9412, "closed": 9398, "active": 14, "normalCloses": 9355, "abnormalCloses": 43 }, "cron": { "fires": 2841, "errors": 3, "active": 0, "wrapperActive": 0 }, "droppedScripts": 0, "sinceMs": 1737534113000}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}GET /api/v1/exec/monitor/scripts
Section titled “GET /api/v1/exec/monitor/scripts”Lists every tracked script with per-script HTTP and WebSocket metrics, including latency percentiles, error counts, and a small ring buffer of recent errors. Sort by activity, volume, errors, or latency to find hot or slow scripts.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | No | Max number of scripts to return. Clamped to [1, 500]. Default 100. |
sort | query | string | No | Sort key. lastActivity (default) sorts by most recent activity; other keys sort descending by the matching metric. Allowed: lastActivity, requests, errors, p95, ws_active. Default "lastActivity". |
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/monitor/scripts?limit=50&sort=p95"const scripts = await client.exec.monitor.listMonitorScripts({ limit: 50, sort: 'p95' });{ "count": 2, "total": 142, "scripts": [ { "scriptPath": "/api/users/[id].js", "hostname": "app.example.com", "vmCached": true, "sharedStateBytes": 4096, "activeHttp": 1, "activeWs": 0, "concurrentRunning": 0, "http": { "total": 42118, "success": 41902, "errors": 216, "meanDurationMs": 18.4, "p50DurationMs": 12.1, "p95DurationMs": 64.8, "maxDurationMs": 982.3 }, "ws": { "opened": 0, "closed": 0, "normalCloses": 0, "abnormalCloses": 0, "meanSessionMs": 0, "maxSessionMs": 0 }, "recentErrors": [ { "timestamp": "2026-01-22T07:58:11.231Z", "statusCode": 500, "message": "TypeError: Cannot read properties of undefined (reading 'id')", "executionId": "exec_01HMZ7VTR2H8X9K3Q4F5PN6MAB" } ], "firstSeenAt": "2026-01-08T14:22:01.000Z", "lastActivityAt": "2026-01-22T08:00:38.901Z" }, { "scriptPath": "/api/orders/checkout.js", "hostname": "app.example.com", "vmCached": true, "sharedStateBytes": null, "activeHttp": 1, "activeWs": 0, "concurrentRunning": 0, "http": { "total": 8214, "success": 8190, "errors": 24, "meanDurationMs": 142.7, "p50DurationMs": 98.2, "p95DurationMs": 312.5, "maxDurationMs": 1842.0 }, "ws": { "opened": 9412, "closed": 9398, "normalCloses": 9355, "abnormalCloses": 43, "meanSessionMs": 18420.1, "maxSessionMs": 318200.4 }, "recentErrors": [], "firstSeenAt": "2026-01-08T14:22:01.000Z", "lastActivityAt": "2026-01-22T08:00:38.901Z" } ]}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}POST /api/v1/exec/monitor/script-performance
Section titled “POST /api/v1/exec/monitor/script-performance”Returns runtime metrics for tracked scripts, including HTTP latency percentiles, recent duration samples, WebSocket session stats, and active request counts. The request body is empty, so the response always contains an empty metrics object {}.
This endpoint takes no path, query, or header parameters.
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/monitor/script-performance"const perf = await client.exec.monitor.getScriptPerformance();{ "metrics": {}}{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}Prometheus Metrics
Section titled “Prometheus Metrics”GET /api/v1/exec/monitor/metrics
Section titled “GET /api/v1/exec/monitor/metrics”Exposes runtime counters in Prometheus 0.0.4 text exposition format. Scrape this endpoint from a Prometheus collector to feed Grafana dashboards. The response includes hoody_exec_http_requests_total, hoody_exec_http_errors_total, hoody_exec_http_duration_ms (per-script histogram), hoody_exec_http_duration_ms_global (aggregate histogram), hoody_exec_ws_connections_active, hoody_exec_ws_closes_total, hoody_exec_metrics_errors_total, and process_start_time_seconds.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/monitor/metrics"const metrics = await client.exec.monitor.prometheusExport();# HELP hoody_exec_http_requests_total Total HTTP requests served# TYPE hoody_exec_http_requests_total counterhoody_exec_http_requests_total{script="/api/users/[id].js"} 42118hoody_exec_http_requests_total{script="/api/orders/checkout.js"} 8214
# HELP hoody_exec_http_errors_total Total HTTP error responses# TYPE hoody_exec_http_errors_total counterhoody_exec_http_errors_total{script="/api/users/[id].js",status="500"} 216
# HELP hoody_exec_http_duration_ms HTTP request duration in ms (per-script histogram)# TYPE hoody_exec_http_duration_ms histogramhoody_exec_http_duration_ms_bucket{script="/api/users/[id].js",le="10"} 18204hoody_exec_http_duration_ms_bucket{script="/api/users/[id].js",le="50"} 39812hoody_exec_http_duration_ms_bucket{script="/api/users/[id].js",le="100"} 41501hoody_exec_http_duration_ms_bucket{script="/api/users/[id].js",le="+Inf"} 42118hoody_exec_http_duration_ms_sum{script="/api/users/[id].js"} 774971.2hoody_exec_http_duration_ms_count{script="/api/users/[id].js"} 42118
# HELP hoody_exec_ws_connections_active Active WebSocket connections# TYPE hoody_exec_ws_connections_active gaugehoody_exec_ws_connections_active 14
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds# TYPE process_start_time_seconds gaugeprocess_start_time_seconds 1737534113{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
# prometheus exporter disabled (--prometheus off){ "error": "Unexpected server error", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}System Control
Section titled “System Control”POST /api/v1/exec/system/restart
Section titled “POST /api/v1/exec/system/restart”Triggers a restart of the exec server. By default the restart is graceful: in-flight requests are drained for up to drainTimeoutMs before the process exits. Call GET /api/v1/exec/system/restart-status first to inspect how many requests are still active.
Request Body
Section titled “Request Body”| Name | Type | Required | Default | Description |
|---|---|---|---|---|
graceful | boolean | No | true | When true, drain in-flight requests before exiting. |
drainTimeoutMs | integer | No | 5000 | Maximum time to wait for in-flight requests to complete during a graceful restart, in milliseconds. |
reason | string | No | "API restart request" | Free-form string recorded in the restart audit log. |
This endpoint takes no path, query, or header parameters.
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.icu/api/v1/exec/system/restart" \ -H "Content-Type: application/json" \ -d '{ "graceful": true, "drainTimeoutMs": 10000, "reason": "Deploying new script bundle" }'await client.exec.system.restartServer({ graceful: true, drainTimeoutMs: 10000, reason: 'Deploying new script bundle'});{ "error": "Invalid parameter format", "code": "VALIDATION_ERROR", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input | Request parameters failed validation | Check parameter format and requirements |
{ "error": "Failed to schedule restart", "code": "ERROR_500", "timestamp": "2026-01-22T08:14:02.481Z", "details": {}}