Logging and Monitoring
Checking Logs
Logs are managed by Docker. You do not need to manually delete log files on the host — rotation is configured in compose.
cd /opt/kopens/plantpulse-ai-docker/bin
./logs.sh # 스택 전체를 따라 본다
./logs.sh plantpulse-copilot-web # 서비스 하나 — compose 서비스 이름 그대로 (여러 개 나열 가능)
./logs.sh --tail 50 # 기본보다 «적게» 보고 싶을 때
-flogs.sh is already followed via -f. The value of --tail appended at the end overrides the default.
You can also invoke compose directly.
cd /opt/kopens/plantpulse-ai-docker
docker compose logs -f --tail=200 plantpulse-rag-api
docker compose logs -f plantpulse-litellm
Which containers to check
| Symptom | Containers to check |
|---|---|
| UI does not load | plantpulse-proxy · plantpulse-copilot-web |
| No response | plantpulse-litellm · plantpulse-llm |
| Cannot find documents | plantpulse-rag-api · plantpulse-lightrag |
| Cannot ingest documents | plantpulse-docling-serve · plantpulse-document-understanding-api |
| Time series analysis fails | plantpulse-timeseries-insight-api · -server |
| Admin console is abnormal | plantpulse-admin-api · plantpulse-admin-web |
| Connector · graph mirror · equipment timeline are abnormal | plantpulse-digital-thread-api · plantpulse-digital-thread-neo4j |
| Video is not indexed · voice queries do not work (in installations with video · audio enabled) | plantpulse-asr · plantpulse-asr-audio · plantpulse-document-understanding-api · plantpulse-rag-api |
The full list of containers and their roles is in Installation Overview.
Observing AI Tool Calls — The Tool Row in Queries and Phoenix
There are two places to see what the AI did while generating a response.
| Location | What | How to open |
|---|---|---|
| Tool row above the query answer (「Used N tools · N seconds」) | Tools called for that answer, values queried, failed tools | Directly in Query (/chat) |
Arize Phoenix (plantpulse-phoenix) | LLM call traces — including prompt · response body | Not open on the host — open with PP_DEBUG_PORTS=1 only when diagnosing → Service Port Map |
Phoenix is part of the default stack and continuously collects traces. From 2026.09, port 6006 is simply not exposed on the host — because it would expose query and response bodies without authentication. The Logs screen for LLM in the Admin Console shows only model · token · latency; the body is available only in Phoenix.
Expanding the tool row attached to each query answer lets you see which tools were called with which values, and if any failed. Rounds executed by Automation are recorded in the automation execution history as 「Evidence — N tool calls」.
Service Status Monitoring
cd /opt/kopens/plantpulse-ai-docker/bin
./status.sh # compose ps + 외부 노출 지점(copliot-web :80) 응답 확인
./health.sh # 위에 더해 호스트 디스크 · 컨테이너 자원 · 서비스별 최근 로그
./doctor.sh # 무엇이 잘못됐는지 진찰 — 아무것도 바꾸지 않습니다
For a quick check, use status.sh; during an outage, view broadly with health.sh then narrow down with doctor.sh.
Health Check Endpoints
| Service | Health Check URL | Notes |
|---|---|---|
| AI Chat Web | http://127.0.0.1/actuator/health | Accessed through the proxy |
| RAG | http://127.0.0.1:7115/health | rag-api. Works without a key (exempt path) |
| Time Series Insights | http://127.0.0.1:8970/health | Works without a key (exempt path) |
| LiteLLM | http://127.0.0.1:4000/health/liveliness | /health may require the master key |
| Admin Console | http://127.0.0.1:5959/health | Container-native health is at /ping. Port is PI_ADMIN_WEB_PORT(default 5959) — use that value if changed. Service status aggregation is in the console UI |
| Digital Thread | Not reachable from the host — Digital Thread API card on the Admin Console home | 7140 is not exposed. The card reads /health, and if the graph mirror projection is failed, it degrades to degraded(yellow). The status of connector periodic synchronization (connector_sync) is also shown here, but it is informational only and does not trigger a yellow indicator |
| Document Understanding | Not reachable from the host — docker exec plantpulse-document-understanding-api python3 -c "import urllib.request;print(urllib.request.urlopen('http://localhost:7120/health').read().decode())" | In installations with video · audio enabled, components.asr.status must be up(disabled installations are disabled — normal). If transcription serving dies, it is degraded |
Previously LightRAG was directly exposed via 7114, but now rag-api(7115) is the only
gateway and LightRAG itself is only inside the container. Do not probe 7114 and conclude it is
dead — it was not there in the first place.
Qdrant · vLLM · Embedding · Reranker · docling · Time series inference · admin-api do not expose
host ports(2026-08-21). Phoenix from 2026.09, and the Digital Thread API(7140) and its dedicated Neo4j from
2026.10 are the same. Because they only call each other inside the container, probing with 127.0.0.1
will not work. If diagnosis is needed, revive them via the debug overlay →
Service Port Map
Since the Platform provides server-web, the health check also looks at the Platform side.
Metrics — /metrics
Since the 2026.10 re-release, five Python backends(RAG · Time Series Insights API · Document Understanding · Vision · Digital Thread) Prometheus
text format metrics at GET /metrics. There is no new port; it is a path attached to each service's original port.
| Service | Metrics address | From host |
|---|---|---|
| RAG | http://127.0.0.1:7115/metrics | Reachable |
| Time Series Insights API | http://127.0.0.1:8970/metrics | Reachable |
| Document Understanding · Vision · Digital Thread | plantpulse-document-understanding-api:7120 · plantpulse-vision-api:7130 · plantpulse-digital-thread-api:7140 of /metrics | Not reachable — scrape within the same compose network |
curl -s -H "X-API-Key: <PI_INBOUND_API_KEY>" http://127.0.0.1:7115/metrics | grep '^http_requests_total' | head
/metrics requires a keyUnlike the health paths(/ping · /health), it is behind the inbound key. When scraping with Prometheus, provide PI_INBOUND_API_KEY via the X-API-Key header or
authorization:(Bearer) configuration. Calling without a key results in 401.
| Metric | Meaning |
|---|---|
http_requests_total | Number of processed requests — by method · path template · status class(2xx etc.) |
http_request_duration_seconds | Request latency histogram — same labels |
http_requests_in_flight | Number of currently in-progress requests |
app_build_info | Service name · version · release(release label, e.g. 2026.10). Value is always 1 |
The path label is a path template, not the actual path, and requests that do not match any route are collapsed into <unmatched> —
no time series is created for each path containing an ID. Basic metrics such as process · GC are also output.
Tracing a single request in logs — X-Request-ID
The same five services assign an id to each request, return it in the response header X-Request-ID, and populate it in every log line during that request
via request_id. If the caller sends a value in X-Request-ID(1–128 characters, alphanumeric · . _ -), that value is used as-is. Use this single value to match errors displayed in the UI to logs.
docker compose logs plantpulse-rag-api 2>&1 | grep '<request_id 값>'
When the Disk is Full
You do not need to manually delete log files — container logs are rotated by Docker. What usually consumes disk space is images and volumes.
docker system df # 무엇이 얼마나 쓰고 있나
docker image prune -f # 태그 없는 옛 이미지 정리
docker volume pruneTwo Neo4j instances · Qdrant · LightRAG storage · time series models trained per installation(pi-ttm-tuned-models) and
TLS certificates are in the volumes. If run while containers are down, the knowledge graph and vector index, as well as models trained in the
field, will be lost.
Since health.sh shows both host disk and container resources, check it before cleaning up.
See Also
- Service Operations — Commands to start and stop
- Service Port Map
- Installation Overview — Roles of the 25 containers