#!/usr/bin/env bash set -Eeuo pipefail NETWORK="${OBSERVABILITY_NETWORK:-han-chat-observability}" COLLECTOR_SERVICE="${COLLECTOR_SERVICE:-otel-collector}" errors=0 ok() { printf 'OK %s\n' "$*"; } fail() { printf 'FAIL %s\n' "$*" >&2; errors=$((errors + 1)); } collector_id="$(docker compose ps -q "$COLLECTOR_SERVICE" 2>/dev/null || true)" if [[ -n "$collector_id" ]] && [[ "$(docker inspect --format '{{.State.Status}}' "$collector_id")" == running ]]; then ok "Collector service is running" else fail "Collector service '$COLLECTOR_SERVICE' is not running" fi for service in sms-service sms-worker; do if docker compose exec -T "$service" python - <<'PY' >/dev/null 2>&1 import os import urllib.request port = os.environ.get("SMS_METRICS_PORT", "9464") if "worker" in os.environ.get("OTEL_SERVICE_NAME", "") else "8080" urllib.request.urlopen(f"http://127.0.0.1:{port}/metrics", timeout=3).read(1024) PY then ok "${service} metrics endpoint" else fail "${service} metrics endpoint" fi done docker run --rm --network "$NETWORK" \ ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest \ traces --otlp-endpoint otel-collector:4317 --otlp-insecure \ --service han-chat-e2e-canary --traces 100 --rate 20 >/dev/null \ && ok "100 canary traces submitted" \ || fail "telemetrygen failed" bad_logs="$( docker compose logs --since=10m "$COLLECTOR_SERVICE" 2>&1 | grep -Ei 'queue is full|connection refused|tls:|Unauthenticated|Permanent error' || true )" if [[ -z "$bad_logs" ]]; then ok "No exporter/queue errors in last 10 minutes" else fail "Collector reports exporter/queue errors" printf '%s\n' "$bad_logs" >&2 fi if ((errors)); then printf 'Observability verification failed: %d check(s)\n' "$errors" >&2 exit 1 fi cat <<'EOF' Локальный канал исправен. В SigNoz проверьте за последние 15 минут: service.name = han-chat-e2e-canary service.namespace = han-chat Затем выполните synthetic API request и проверьте общий trace между api-backend и dependency spans, service.version и deployment.environment. EOF