github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/status/status.go (about) 1 // Package status is here just to say that the API is up and that it can 2 // access the CouchDB databases, for debugging and monitoring purposes. 3 package status 4 5 import ( 6 "context" 7 "net/http" 8 "sync" 9 "time" 10 11 "github.com/cozy/cozy-stack/pkg/assets/dynamic" 12 "github.com/cozy/cozy-stack/pkg/config/config" 13 "github.com/cozy/cozy-stack/pkg/couchdb" 14 "github.com/labstack/echo/v4" 15 ) 16 17 // Status responds with the status of the service 18 func Status(c echo.Context) error { 19 cache := "healthy" 20 couch := "healthy" 21 fs := "healthy" 22 23 latencies := map[string]string{} 24 var mu sync.Mutex 25 var wg sync.WaitGroup 26 wg.Add(3) 27 28 ctx, cancel := context.WithTimeout(c.Request().Context(), 5*time.Second) 29 defer cancel() 30 31 go func() { 32 cfg := config.GetConfig() 33 if lat, err := cfg.CacheStorage.CheckStatus(ctx); err == nil { 34 mu.Lock() 35 latencies["cache"] = lat.String() 36 mu.Unlock() 37 } else { 38 cache = err.Error() 39 } 40 wg.Done() 41 }() 42 43 go func() { 44 if lat, err := couchdb.CheckStatus(ctx); err == nil { 45 mu.Lock() 46 latencies["couchdb"] = lat.String() 47 mu.Unlock() 48 } else { 49 couch = err.Error() 50 } 51 wg.Done() 52 }() 53 54 go func() { 55 if lat, err := dynamic.CheckStatus(ctx); err == nil { 56 mu.Lock() 57 latencies["fs"] = lat.String() 58 mu.Unlock() 59 } else { 60 fs = err.Error() 61 } 62 wg.Done() 63 }() 64 65 wg.Wait() 66 code := http.StatusOK 67 status := "OK" 68 if cache != "healthy" || couch != "healthy" || fs != "healthy" { 69 code = http.StatusBadGateway 70 status = "KO" 71 } 72 73 return c.JSON(code, echo.Map{ 74 "cache": cache, 75 "couchdb": couch, 76 "fs": fs, 77 "status": status, 78 "latency": latencies, 79 "message": status, // Legacy, kept for compatibility 80 }) 81 } 82 83 // Routes sets the routing for the status service 84 func Routes(router *echo.Group) { 85 router.GET("", Status) 86 router.HEAD("", Status) 87 router.GET("/", Status) 88 router.HEAD("/", Status) 89 }