Loodud 2026-09-25. ClickStack = HyperDX UI + (väline) ClickHouse + kaasas olev
OTel-kollektor. Kogu grupp on always-on (ei ole enam experimental).
clickstack-proxy)admin@odamus.com / Dev_clickhouse_2026!clickhouse konteiner): HTTP 8125, native 9004 (Tailscale-only)node-exporter ─┐
cadvisor ──────┼─► otel-collector (scrape 60s) ─► clickstack:4317 (kaasas kollektor) ─► ClickHouse (default.otel_*)
llama.cpp ─────┘ (main_ai_network) (opampsupervisor)
otel-collector (contrib) skrape'ib node-exporter, cadvisor ja llama.cpp (host.docker.internal:8070/metrics).otel_* tabelitesse.clickstack-entry.sh peab käivitama /otel-entrypoint.sh /usr/local/bin/opampsupervisor — muidu OTLP andmed ei püsi.otel_logs, otel_traces, otel_metrics_gauge|sum|histogram|exponential_histogram|summary + rollupid.
Skeem luuakse automaatselt schema-seed'iga (goose).
| Fail | Sisu |
|---|---|
dev/docker-compose.yml |
clickstack, clickstack-proxy, node-exporter, cadvisor, otel-collector (always-on) |
dev/config/otel-collector/config.yaml |
prometheus receiver (node/cadvisor/llamacpp) + regexp-filter + OTLP eksport |
dev/clickstack-entry.sh |
mongod + OTel-kollektor + HyperDX app |
dev/.env |
HYPERDX_INGEST_KEY (gitignore'itud) — kollektori OTLP auth |
CLICKHOUSE_ENDPOINT=tcp://clickhouse:9000?dial_timeout=10sCLICKHOUSE_USER=default, CLICKHOUSE_PASSWORD=dev_clickhouse_2026HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE=defaultDEFAULT_CONNECTIONS=[{"name":"Local ClickHouse","host":"http://clickhouse:8123","username":"default","password":"dev_clickhouse_2026"}]Ühendusel peavad olema eraldi väljad username/password ja host ilma
userinfo'ta (http://clickhouse:8123). Siis lisab CH-proxy X-ClickHouse-User/Key päised.
❗ Local mode peab olema VÄLJAS:
NEXT_PUBLIC_IS_LOCAL_MODE=false. Koos välise (mitte-image'sisese) ClickHouse'iga põhjustabtrueselle, et brauser kasutab lokaalset ühendust (sessionStorage/__ENV.js) ja saadab iseAuthorization/user=→ proxy lisab omakordaX-ClickHouse-*→ Code 516 võiUNKNOWN_USER. Väärtus injekteeritakse runtime'ispublic/__ENV.jskaudu → piisabdocker compose up -d --force-recreate clickstack(kontroll:cat .../public/__ENV.js).❗ Varasem soovitus hoida
username/passwordtühjad ja panna tunnused host-URL-i (http://default:parool@clickhouse:8123) ei tööta:http-proxy-middlewareei edasta host-URL-i parooli → CH saab kasutajadefaulttühja parooliga → „Authentication failed: password is incorrect". (Kinnitatudtcpdump -i any 'tcp port 8123'-ga.)
Mongo otsene parandus:
db.connections.updateOne({_id: ObjectId("<conn-id>")},
{$set:{host:"http://clickhouse:8123", username:"default", password:"dev_clickhouse_2026"}});
Pärast otsest mongo-muudatust taaskäivita
clickstack(muidu jääb vahemällu):docker restart clickstack.
Code 516 hoiatus: kui ühendusel on username JA päring sisaldab user= query-param,
tuleb Code: 516 ... X-ClickHouse HTTP headers and authentication via parameters simultaneously.
Seetõttu ei tohi ühendust anda browseri CH-kliendile koos username'iga; HyperDX metadataklient
(W({queryTimeout})) ehitab kliendi ilma username'ita → OK.
otel-collector loeb Dockeri konteineriloge:
receivers.filelog: include: /var/lib/docker/containers/*/*-json.log, container parser, start_at: endservice.pipelines.logs: [filelog] → [memory_limiter, batch] → [otlp]otel-collector vajab mounti /var/lib/docker/containers:/var/lib/docker/containers:ro
ja user: "0:0" (mitte-root kasutaja → „open .: permission denied").SELECT count(), max(Timestamp) FROM default.otel_logs.--metrics).HyperDX UI-s: Dashboards → New dashboard → Add tile. Kasuta allolevaid metrikaid
(Metrics source) või "SQL" diagrammi. Ajatelje jaoks sobib TimeUnix.
| Paneel | Mõõdik / SQL |
|---|---|
| RAM vaba | node_memory_MemAvailable_bytes (gauge) |
| Swap vaba | node_memory_SwapFree_bytes (gauge) |
| Load | node_load1 (gauge) |
| Konteineri mälu | container_memory_working_set_bytes (group: Attributes['name']) |
| Konteineri CPU | container_cpu_usage_seconds_total (rate) |
| Llama tokeneid/s | rate(llamacpp:tokens_predicted_total) või pika aja trend |
| Llama päringud | llamacpp:requests_processing (gauge), llamacpp:tokens_predicted_total (sum) |
| Llama KV-cache | llamacpp:kv_cache_usage_ratio (gauge) |
| Teenus üleval | ohmu_service_up (group: Attributes['service']) |
| Restardid | ohmu_container_restarts (group: Attributes['name']) |
Näidis-SQL (ClickHouse):
-- Teenuste seis viimase 10 min jooksul
SELECT toStartOfMinute(TimeUnix) AS t, Attributes['service'] AS service, avg(Value) AS up
FROM default.otel_metrics_gauge
WHERE MetricName = 'ohmu_service_up' AND TimeUnix > now() - INTERVAL 10 MINUTE
GROUP BY t, service ORDER BY t;
select skeem (HyperDX 2.37)Metrika-diagramm ja alert nõuavad, et select[] elemendil oleks:
{metricName, metricType, aggFn, isDelta, filters: [], valueExpression: "Value"},
kus metricType ∈ gauge|sum|histogram|summary|exponential histogram.
Vana aggCondition-ainult kuju annab no query support for metric type=undefined.
valueExpression on vajalik, sest alerti config lisab variables → macro-töötlus loeb
select[].valueExpression (puudumisel TypeError: Cannot read properties of undefined (reading 'length')).
metricType määra ClickHouse'i tabeli järgi (otel_metrics_gauge|sum|histogram|...):
nt llamacpp:tokens_predicted_total → sum, node_load1/ohmu_service_up → gauge.
Alert ei toeta table-paneeli (Unsupported alert source: tile). Kasuta
number/line/stacked bar paneeli. Pärast alerti/paneeli otsest mongo-muudatust
taaskäivita clickstack (vahemälu).
Syntax error ... toString() (tühi valueExpression + count)Sama juur kui heatmap'il allpool: min/max päring kasutab tühja valueExpression-i.
Vaikimisi seeria {aggFn:"count", valueExpression:""} → toFloat64OrDefault(toString()) →
Code: 62 SYNTAX_ERROR ... position 58 (>=). Lahendus: kas anna Value-le arvuline
veerg (nt SeverityNumber) või vaheta kuva table-ks (min/max päringut ei tehta).
Value = 1 väldib küll vea, aga annab skaala 1..1 (ei sobi graafikule). Upstream viga.
valueExpression → Syntax error ... toString()HyperDX 2.37 arvutab heatmap'i/joongraafiku min/max tooresest select[0].valueExpression-ist
(app-chunk 4719-*, funktsioon A): quantileIf(0.01)(toFloat64OrDefault(toString(<expr>)), <expr> >= 0 ...).
Kui expr on tühi (vaikimisi count-seeria), tekib toString()) + >= 0 → Code: 62 SYNTAX_ERROR.
Sama kehtib heatmap'i „Low/High" legendile. See on upstream viga, mitte andmeviga.
Kontrollitud lahendused (Logs otel_logs):
| Value expression | Tulemus |
|---|---|
| "" (vaikimisi) | ❌ süntaksiviga |
| 1 | ✅ töötab, aga skaala 1..1 (flat — ei sobi) |
| SeverityNumber / TraceFlags | ✅ töötab, sisuline skaala |
| count() | ❌ agregaadi pesastamine (quantileIf(count())) — keelatud |
Soovitus: heatmap (ja y-telg) vajab arvulist veergu, mitte count'i:
SeverityNumber (või TraceFlags), „Group by" nt ServiceName.Value (või avg(Value)), filter MetricName.table) kuni upstream-paranduseni.PATCH (meil rakendatud): bind-mount'itud kolm chunki:
dev/patches/4719-70b065addcfc053d.js(jagatud, dashboardid),dev/patches/pages/clickhouse-46029ebbad38b40a.js(/chartleht; funktsioonidN+F) jadev/patches/4751-53b929fca5a575a9.js(heatmap-valideerimine). Patch teeb tühjavalueExpression'i korral count-põhise min/max'i ja bucket-päringu, seega count-heatmap/graafik töötab ilma Value't täitmata. Täiendused (02.10.2026):
- CTE count-selectid (
min_max_calc/bucket_calc) said väljadvalueExpression:"",aggCondition:"",aggConditionLanguage:"lucene"— muiducommon-utilsCTE-skeem andis „non-conforming chartConfig object in CTE".4751-…: heatmap-valideerimine lubab tühjavalueExpression, kuiseries[0].aggFn==="count"— muidu „Value expression is required for heatmap charts". ⚠️ Chunkid onCache-Control: immutable→ vaja hard-refresh (Ctrl+Shift+R). ⚠️ Patchid on seotud chunk-hashiga (HyperDX 2.37.0, image...all-in-one:latest). Image'i uuendusel: võrdle uut chunk-nime ja kohanda patch + mount. Kontroll:curl .../chunks/pages/clickhouse-*.js | grep 'r||!a'.
container operatori add_metadata_from_filepath (vaikimisi true) ootab Kubernetes'i
tee-mustrit (logpathPattern); Docker-teed (/var/lib/docker/containers/<id>/<id>-json.log)
ei sobi → iga logirea kohta viga (cadvisor jt). Parandus otel-collector config'us:
add_metadata_from_filepath: false (pole k8s). Kontroll:
docker logs otel-collector --since 3m | grep -c "failed to detect a valid log path" → 0.
Service Map on trace-põhine. Kui URL-is on ?source=<logSourceId>, näitab UI hoiatust
„... is a log source, which this page can't show" — vali päises Traces või ava
http://100.87.1.24:18080/service-map?source=6a95600db1eca667454bec7e.
Instrumenteeritud (OTel auto-instrumentation, opentelemetry-distro + OTLP gRPC):
nutikodu-web (FastAPI/uvicorn) — Server + Client spanid (ClickHouse HTTP)weather-collector, zigbee-collector — Client spanid (Open-Meteo, ClickHouse, MQTT)Andmevoog: app OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 →
otel-collector (otlp receiver → traces pipeline) → clickstack:4317 → default.otel_traces.
Dockerfile'ides: pip install opentelemetry-distro opentelemetry-exporter-otlp-proto-grpc &&
opentelemetry-bootstrap -a install, CMD ["opentelemetry-instrument", ...].
Kontroll: SELECT ServiceName, SpanKind, count() FROM default.otel_traces GROUP BY 1,2.
metricTables.exponentialHistogramVaikimisi bootstrap võib selle puudumisel metrikate valija katki teha. Kontroll:
docker exec clickstack mongo --quiet hyperdx --eval \
'printjson(db.sources.findOne({kind:"metric"}).metricTables)'
# vajadusel: db.sources.updateOne({kind:"metric"},{$set:{"metricTables.exponentialHistogram":"otel_metrics_exponential_histogram"}})
Loodud 2026-09-25 skriptiga ~/scripts/create_hyperdx_dashboards.py:
ohmu_service_up, ohmu_container_restartsKordamine: python3 ~/scripts/create_hyperdx_dashboards.py (--delete-tests koristab testid).
API ligipääs: HyperDX väline API v2 on http://<clickstack-ip>:8000/api/v2
(hostilt konteineri IP kaudu; clickstack-proxy ribab /api prefiksi, seega :18080 kaudu ei tööta).
Access key: docker exec clickstack mongo --quiet hyperdx --eval 'print(db.users.findOne({email:"admin@odamus.com"}).accessKey)'.
Tile-vorming (API):
{"name":"paneel","x":0,"y":0,"w":6,"h":6,"config":{
"displayType":"line","sourceId":"<Metrics source id>",
"select":[{"valueExpression":"Value","aggFn":"avg","where":"MetricName:\"node_load1\""}],
"groupBy":"name"}}
Rakendatud: HyperDX webhook → alert-relay → Telegram.
alert-relay konteiner (dev/config/alert-relay/alert_relay.py, python:3.12-slim, port 9099):
võtab vastu HyperDX „generic" webhook POST-id ja saadab Telegrami. Token dev/.env-st
(TELEGRAM_BOT_TOKEN), chat 5036685258.
⚠️ HyperDX generic webhook saadab {"text": "..."} (Slack-laadne) — relay saadab selle
otse, ilma parse_mode-ita (Markdown [ ] * _ põhjustaks Telegrami parse-vea).
Varem ootas välju name/state/message → kuvas „Seis: ?" + toor-JSON (parandatud 02.10.2026).Telegram (ohmu) → http://alert-relay:9099/ (id 6ab760240c9282a5b0fde124).thresholdType=below, threshold=1, interval=5m, numConsecutiveWindows=2
(nõuab 2 järjestikust akent → väldib üksiku andmeaugu valehäiret), kanal webhook
(id 6ab7603c0c9282a5b0fde12d).Oluline API-piirang: väline API v2 (POST /api/v2/alerts) toetab ainult
source: "tile" või "saved_search" — inline alert on ainult sisemise API jaoks.
Paneeli-alert viitab: {source:"tile", tileId, dashboardId}; kanal:
{"type":"webhook","webhookId":"..."}.
Testimine:
# relay otse (hostilt pole 9099 avaldatud; kasuta konteinerit võrgus):
docker run --rm --network main_ai_network curlimages/curl:latest -s \
-X POST http://alert-relay:9099/ -H 'Content-Type: application/json' \
-d '{"text":"🚨 test (ignoreeri)"}'
Tüüpilised täiendavad alertid (sama muster: tile + webhook + below/above):
node_memory_MemAvailable_bytes < X (RAM otsas)ohmu_container_restarts > 0 (restart-loop)llamacpp:kv_cache_usage_ratio > 0.9Clickstack'i kaasasolev OTLP-collector (opampsupervisor) teeb käivitusel ClickHouse'i skeemi
seed'i; kui ClickHouse pole sel hetkel kättesaadav (dial tcp <ip>:9000: connection refused),
collector sureb → OTLP 4317/4318 on maas → kõik meetrikad/logid/trace'id seiskusid
(ja ohmu_app_metrics.py logib [Errno 104] Connection reset by peer). Kuna ohmu_service_up
andmeid ei tule, arvutab alert'i min() tühja akna pealt 0 → vale „Teenus maas" häire.
Ravi: docker restart clickstack (seed õnnestub, collector tuleb tagasi, 4318 → 200).
✅ Parandatud (02.10.2026): docker-compose.yml-is lisatud
clickhouse healthcheck native TCP 9000 vastu
(clickhouse-client --password "$CLICKHOUSE_PASSWORD" --query 'SELECT 1', 10s intervall, start_period 30s);clickstack depends_on: clickhouse: condition: service_healthy.
Nüüd ootab clickstack ClickHouse'i tervist enne käivitumist → collector'i seed ei jookse enam
ClickHouse'i käivitumise ajal. Kontroll: docker compose up -d clickhouse clickstack →
clickhouse Waiting → Healthy → clickstack Starting. (Käsitsi ikka: docker restart clickstack.)
Kontroll: docker exec clickstack sh -c 'tail -3 /var/log/otel-collector.log' (peab olema
Schema seed completed successfully + Connected to the OpAMP server); OTLP-test: curl -X POST
-H 'authorization: <INGEST_KEY>' http://127.0.0.1:4318/v1/metrics → 200.
(Pikaajaline: collector võiks seed'i ebaõnnestumisel retry'da, mitte surra — upstream.)Sessions (_id 6a95600db1eca667454bec83, from default.hyperdx_sessions,
seotud Traces-allikaga). Andmeid kogub HyperDX Browser SDK (@hyperdx/browser).02a19ecf-f62e-4e17-819f-3ee1498d69f3 (= team apiKey = HYPERDX_INGEST_KEY).
⚠️ HYPERDX_API_KEY peab olema sama (ka API logger kasutab seda); varem oli vale
(790900ff…) → /api/config andis vale key ja API logid said 401.https://otel.odamus.com (edge Caddy → 100.87.1.24:4318; CORS OK:
OPTIONS 204, Allow-Origin *). DNS: DO A otel.odamus.com → 188.166.84.16.Snippet (rakendustes enne </body>; key on serveripoolne ingest-key, brauseris nähtav — HyperDX standard):
<script src="https://unpkg.com/@hyperdx/browser@0.26.0/build/index.js"></script>
<script>if(window.HyperDX){HyperDX.init({apiKey:'02a19ecf-f62e-4e17-819f-3ee1498d69f3',
service:'<app>',url:'https://otel.odamus.com',consoleCapture:true,
advancedNetworkCapture:true,maskAllInputs:true,maskAllText:true});}</script>
Instrumenteeritud: veebipood (app/templates/base.html), liiklusatlas
(web/index.html, web/tutvustus.html), nutikodu-web (static/index.html), HyperDX UI ise
(/api/config env-iga: HYPERDX_API_KEY + NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT).
Dashboard: „Ohmu — sessioonid (client)" (_id 6ac014f48475db7c237f16fe) —
sessioonid ajas (line) + teenuse kaupa (table), source = session-allikas.
Kontroll: SELECT ServiceName, count() FROM default.hyperdx_sessions GROUP BY ServiceName.
otel.odamus.com)Avalik ingest on rate-limiteeritud: edge Caddy → otel-ratelimit (nginx, 100.87.1.24:4319,
limit_req zone=otlp 20r/s burst=60 nodelay, limit_conn 40, real IP X-Forwarded-For kaudu,
set_real_ip_from 100.64.0.0/10) → clickstack:4318.
(Caddy standardbuildis rate_limit plugin't pole → seetõttu nginx.)
Konfiguratsioon: dev/config/otel-ratelimit/nginx.conf, teenus dev/docker-compose.yml.
Kontroll: 150 kiiret POST-i → ~62×200, ~88×429.
cadvisor logib korduvalt
Unable to get btrfs mountpoint IDs: stat failed on /dev/mapper/data-root — benignne
(konteiner ei näe hosti LVM-seadet, cAdvisor langeb tagasi). otel-collector filter/logs
processor (IsMatch(body, "Unable to get btrfs mountpoint IDs")) viskab need välja.
Logs-pipeline: [filelog] → [memory_limiter, filter/logs, batch] → [otlp].
../LOEMIND_seisevad_konteinerid.md~/servers/LOEMIND/llama-server.md