Добавлены метрики Prometheus и дашборды Grafana (этап 2.5)
Все три Go-сервиса (ingest, device-control, rule-engine) отдают /metrics в формате Prometheus: счётчики MQTT/RabbitMQ/ClickHouse операций, гистограммы длительности батч-флашей и диспатча правил, переходы устройств online/offline. Добавлены сервисы prometheus и grafana в docker-compose с провижининг конфигом (datasource + два готовых дашборда: "Ingest & Telemetry" и "Automation & Devices").
This commit is contained in:
@@ -16,12 +16,14 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
devicecontrol "git.cactoz.su/cacto/home_automatization/proto/device_control"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/config"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/healthcheck"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/httpapi"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/metrics"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/mqttclient"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/rabbitmq"
|
||||
"git.cactoz.su/cacto/home_automatization/services/device-control-service/internal/server"
|
||||
@@ -74,6 +76,8 @@ func run(logger *slog.Logger) error {
|
||||
}
|
||||
|
||||
checker := healthcheck.New(shadowStore, cfg.HealthCheckTimeout, cfg.HealthCheckInterval, func(deviceID string) {
|
||||
metrics.HealthTransitionsTotal.WithLabelValues("offline").Inc()
|
||||
|
||||
pubCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if err := publisher.PublishStatusChanged(pubCtx, deviceID, shadow.StatusOffline); err != nil {
|
||||
@@ -93,10 +97,14 @@ func run(logger *slog.Logger) error {
|
||||
devicecontrol.RegisterDeviceControlServer(grpcServer, srv)
|
||||
|
||||
// Same server instance, second transport — for callers where a full
|
||||
// gRPC client is impractical (Laravel/PHP; see README).
|
||||
// gRPC client is impractical (Laravel/PHP; see README). /metrics rides
|
||||
// along on this same port rather than opening a third one.
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", httpapi.NewRouter(srv, logger))
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
httpServer := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", cfg.HTTPPort),
|
||||
Handler: httpapi.NewRouter(srv, logger),
|
||||
Handler: mux,
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -145,8 +153,10 @@ func telemetryHandler(store *shadow.Store, publisher *rabbitmq.Publisher, logger
|
||||
deviceID, ok := deviceIDFromTopic(topic)
|
||||
if !ok {
|
||||
logger.Warn("dropping telemetry from unparseable topic", "topic", topic)
|
||||
metrics.MQTTEventsTotal.WithLabelValues("telemetry", "invalid").Inc()
|
||||
return
|
||||
}
|
||||
metrics.MQTTEventsTotal.WithLabelValues("telemetry", "ok").Inc()
|
||||
touch(context.Background(), store, publisher, deviceID, logger)
|
||||
}
|
||||
}
|
||||
@@ -160,14 +170,17 @@ func ackHandler(store *shadow.Store, publisher *rabbitmq.Publisher, logger *slog
|
||||
deviceID, ok := deviceIDFromTopic(topic)
|
||||
if !ok {
|
||||
logger.Warn("dropping ack from unparseable topic", "topic", topic)
|
||||
metrics.MQTTEventsTotal.WithLabelValues("ack", "invalid").Inc()
|
||||
return
|
||||
}
|
||||
|
||||
var ack ackPayload
|
||||
if err := json.Unmarshal(payload, &ack); err != nil {
|
||||
logger.Warn("dropping invalid ack payload", "device_id", deviceID, "error", err)
|
||||
metrics.MQTTEventsTotal.WithLabelValues("ack", "invalid").Inc()
|
||||
return
|
||||
}
|
||||
metrics.MQTTEventsTotal.WithLabelValues("ack", "ok").Inc()
|
||||
|
||||
ctx := context.Background()
|
||||
if len(ack.State) > 0 {
|
||||
@@ -186,6 +199,8 @@ func touch(ctx context.Context, store *shadow.Store, publisher *rabbitmq.Publish
|
||||
return
|
||||
}
|
||||
if becameOnline {
|
||||
metrics.HealthTransitionsTotal.WithLabelValues("online").Inc()
|
||||
|
||||
pubCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
if err := publisher.PublishStatusChanged(pubCtx, deviceID, shadow.StatusOnline); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user