SearchOps Phase 6 adds small, local-friendly backend observability. It does not add a production monitoring stack.
Phase 7 keeps this scope unchanged and documents the implemented /metrics
endpoint in OpenAPI and README. CI verifies the endpoint through backend tests;
it does not provision Prometheus, Grafana, tracing, alerting, or production log
aggregation.
The backend uses Pino for JSON structured logs.
Startup, shutdown, request completion, unhandled request errors, unhandled promise rejections, and uncaught exceptions are logged through the shared application logger.
Request completion logs include:
requestIdmethodpathroutestatusCodedurationMs
Log levels:
infofor normal completed requestswarnfor slow completed requestserrorfor 5xx responses and unhandled errors
The default slow request threshold is 500ms. It can be changed locally with SLOW_REQUEST_THRESHOLD_MS.
The existing x-request-id behavior is preserved.
If a request includes x-request-id, the backend reuses it. Otherwise the backend generates one and returns it in the x-request-id response header and API response meta.requestId.
The backend exposes:
GET /metricsThis is an infrastructure endpoint and is not mounted under /api.
The response is Prometheus-style text and is not wrapped in the normal JSON API envelope.
Implemented metrics:
http_requests_totalhttp_errors_totalhttp_request_duration_mshistogramsearch_latency_simulation_total
HTTP metrics use these labels:
methodroutestatusCode
Example:
http_requests_total{method="GET",route="/api/jobs",statusCode="200"} 3
http_request_duration_ms_count{method="GET",route="/api/jobs",statusCode="200"} 3
http_errors_total{method="GET",route="/missing",statusCode="404"} 1
search_latency_simulation_total{route="/api/jobs"} 1Phase 6 includes a controlled local-only incident simulation for GET /api/jobs.
The simulation only runs when both are true:
ENABLE_INCIDENT_SIMULATION=trueNODE_ENVis notproduction
The delay is triggered per request, not globally for every request.
Supported triggers:
GET /api/jobs?simulateSlowSearch=trueor:
x-searchops-simulate-latency-ms: 1200The maximum simulated delay is capped at 3000ms.
When triggered, the backend:
- delays only that
GET /api/jobsrequest - increments
search_latency_simulation_total - logs
search latency simulation triggeredwithrequestId,route, anddelayMs - records the slower request in
http_request_duration_ms
curl http://localhost:5000/health
curl http://localhost:5000/metrics
curl "http://localhost:5000/api/jobs?limit=3"
curl "http://localhost:5000/api/jobs?limit=3&simulateSlowSearch=true"
curl -H "x-searchops-simulate-latency-ms: 1200" "http://localhost:5000/api/jobs?limit=3"These are intentionally not implemented in Phase 6:
- Prometheus server
- Grafana dashboards
- OpenTelemetry tracing
- distributed tracing
- alert rules or paging
- log aggregation
- log rotation
- CloudWatch or other managed monitoring
- production dashboards
- authentication
- rate limiting
- deployment monitoring
Future production work could add those pieces around the Phase 6 logs and metrics. Until then, /metrics and container logs are local operational signals only.
- Pino JSON structured application logs
- request completion logs with request IDs and durations
- warning logs for slow requests
- error logs for 5xx responses and unhandled request errors
-
GET /healthpreserved -
GET /metricsPrometheus-style text endpoint - HTTP request, error, and duration metrics
- local-only controlled search latency simulation
- simulation metric and log signal
- tracing
- alerting
- dashboards
- production log aggregation
See incident-response.md for the local incident simulation runbook.