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  }