Sfoglia il codice sorgente

feat: add kafka and db health status

master
Blaz Smehov 1 settimana fa
parent
commit
3309f6eeed
8 ha cambiato i file con 72 aggiunte e 4 eliminazioni
  1. BIN
      bridge
  2. BIN
      decoder
  3. +7
    -1
      internal/app/server/events.go
  4. +44
    -0
      internal/app/server/healthcheck.go
  5. +10
    -0
      internal/pkg/common/appcontext/context.go
  6. +11
    -3
      internal/pkg/common/appcontext/health.go
  7. BIN
      location
  8. BIN
      server

BIN
bridge Vedi File


BIN
decoder Vedi File


+ 7
- 1
internal/app/server/events.go Vedi File

@@ -13,15 +13,21 @@ import (
)

// RunEventLoop runs the server event loop until ctx is cancelled.
// Handles: location events -> LocationToBeaconService, alert events -> update tracker in DB, ticker -> publish trackers to mqtt.
// Handles: location events -> LocationToBeaconService, alert events -> update tracker in DB, ticker -> publish trackers to mqtt, health ticker -> Kafka and DB status.
func RunEventLoop(ctx context.Context, a *ServerApp) {
beaconTicker := time.NewTicker(config.MEDIUM_TICKER_INTERVAL)
defer beaconTicker.Stop()
healthCheckTicker := time.NewTicker(config.LARGE_TICKER_INTERVAL)
defer healthCheckTicker.Stop()

for {
select {
case <-ctx.Done():
return
case <-healthCheckTicker.C:
kafkaSt := CheckKafkaHealth(ctx, a.Cfg.KafkaURL)
dbSt := CheckDBHealth(ctx, a.DB)
a.AppState.UpdateServerHealth(kafkaSt, dbSt)
case msg := <-a.ChHealthLocation:
a.AppState.UpdateLocationHealth(msg)
case msg := <-a.ChHealthDecoder:


+ 44
- 0
internal/app/server/healthcheck.go Vedi File

@@ -0,0 +1,44 @@
package server

import (
"context"
"strings"
"time"

"github.com/AFASystems/presence/internal/pkg/common/appcontext"
"github.com/segmentio/kafka-go"
"gorm.io/gorm"
)

const healthCheckTimeout = 3 * time.Second

// CheckKafkaHealth dials the broker and returns ServiceStatus. Uses first broker from kafkaURL (comma-separated).
func CheckKafkaHealth(ctx context.Context, kafkaURL string) appcontext.ServiceStatus {
if kafkaURL == "" {
return appcontext.ServiceStatus{Status: "down", Message: "no broker URL"}
}
broker := strings.TrimSpace(strings.Split(kafkaURL, ",")[0])
tctx, cancel := context.WithTimeout(ctx, healthCheckTimeout)
defer cancel()
dialer := &kafka.Dialer{Timeout: healthCheckTimeout}
conn, err := dialer.DialContext(tctx, "tcp", broker)
if err != nil {
return appcontext.ServiceStatus{Status: "down", Message: err.Error()}
}
_ = conn.Close()
return appcontext.ServiceStatus{Status: "up"}
}

// CheckDBHealth pings the database and returns ServiceStatus.
func CheckDBHealth(ctx context.Context, db *gorm.DB) appcontext.ServiceStatus {
sqlDB, err := db.DB()
if err != nil {
return appcontext.ServiceStatus{Status: "down", Message: err.Error()}
}
tctx, cancel := context.WithTimeout(ctx, healthCheckTimeout)
defer cancel()
if err := sqlDB.PingContext(tctx); err != nil {
return appcontext.ServiceStatus{Status: "down", Message: err.Error()}
}
return appcontext.ServiceStatus{Status: "up"}
}

+ 10
- 0
internal/pkg/common/appcontext/context.go Vedi File

@@ -78,6 +78,8 @@ func NewAppState() *AppState {
ActiveBeacons: []string{},
},
},
Kafka: ServiceStatus{Status: "unknown"},
Database: ServiceStatus{Status: "unknown"},
},
}
}
@@ -106,6 +108,14 @@ func (m *AppState) UpdateBridgeHealth(h BridgeHealth) {
m.mu.Unlock()
}

// UpdateServerHealth updates Kafka and database status (called by server after checking broker and DB).
func (m *AppState) UpdateServerHealth(kafka, database ServiceStatus) {
m.mu.Lock()
m.health.Kafka = kafka
m.health.Database = database
m.mu.Unlock()
}

func (m *AppState) GetLocationHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
m.health.Location.GetUptime(m.startTime)
m.health.Location.GetActiveReaders(k)


+ 11
- 3
internal/pkg/common/appcontext/health.go Vedi File

@@ -7,6 +7,12 @@ import (
"github.com/AFASystems/presence/internal/pkg/kafkaclient"
)

// ServiceStatus represents the health of an external service (e.g. Kafka, database).
type ServiceStatus struct {
Status string `json:"status"` // "up", "down", "unknown"
Message string `json:"message,omitempty"`
}

type BaseHealth struct {
Uptime time.Duration `json:"uptime"`
ActiveReaders []string `json:"activeReaders" gorm:"type:jsonb"`
@@ -29,9 +35,11 @@ type BridgeHealth struct {
}

type Health struct {
Location LocationHealth `gorm:"embedded;embeddedPrefix:loc_"`
Decoder DecoderHealth `gorm:"embedded;embeddedPrefix:dec_"`
Bridge BridgeHealth `gorm:"embedded;embeddedPrefix:brg_"`
Location LocationHealth `json:"location" gorm:"embedded;embeddedPrefix:loc_"`
Decoder DecoderHealth `json:"decoder" gorm:"embedded;embeddedPrefix:dec_"`
Bridge BridgeHealth `json:"bridge" gorm:"embedded;embeddedPrefix:brg_"`
Kafka ServiceStatus `json:"kafka"`
Database ServiceStatus `json:"database"`
}

func (b *BaseHealth) GetUptime(startTime time.Time) {


BIN
location Vedi File


BIN
server Vedi File


Caricamento…
Annulla
Salva