Files
IoT/internal/service/api/handler/admin.go
T

59 lines
1.9 KiB
Go

// admin.go — статистика для страницы администратора.
//
// Endpoint: GET /iot-admin/stats (Bearer ADMIN_STATS_TOKEN).
// Источники: PostgreSQL (iotpg), shared-SQS (атрибуты очереди), рантайм процесса.
// k8s-статусы подов убраны — компоненты теперь в одном процессе.
package handler
import (
"context"
"net/http"
"strings"
"time"
)
// AdminStats — GET /iot-admin/stats.
func (h *Handler) AdminStats(w http.ResponseWriter, r *http.Request) {
if h.Cfg.AdminStatsToken == "" {
writeJSON(w, http.StatusServiceUnavailable, errResp("admin stats not configured: ADMIN_STATS_TOKEN not set"))
return
}
authHeader := r.Header.Get("Authorization")
if !strings.HasPrefix(authHeader, "Bearer ") || strings.TrimPrefix(authHeader, "Bearer ") != h.Cfg.AdminStatsToken {
writeJSON(w, http.StatusUnauthorized, errResp("unauthorized"))
return
}
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
defer cancel()
result := map[string]any{
"collected_at": time.Now().UTC(),
}
// PostgreSQL: статистика по всем tenant (как в старом коде).
if h.IoTPG != nil {
pgStats, err := h.IoTPG.GetAdminStats(ctx)
if err != nil {
result["postgres"] = map[string]any{"reachable": false, "error": err.Error()}
} else {
result["postgres"] = pgStats
}
} else {
result["postgres"] = map[string]any{"reachable": false, "error": "IoTPG not configured"}
}
// SQS: approximate counts очереди телеметрии.
result["sqs"] = h.collectSQSStats(ctx)
// Рантайм процесса (вместо статусов k8s-подов).
result["runtime"] = map[string]any{
"version": h.Version,
"uptime_sec": int64(time.Since(h.StartedAt).Seconds()),
"started_at": h.StartedAt.UTC().Format(time.RFC3339),
}
writeJSON(w, http.StatusOK, result)
}