Logs for liveness and readiness endpoints + PG conn stats (#2460)

* error logs for liveness and readiness endpoints with pg information

* use context timeout of 3 seconds

* context
This commit is contained in:
Mohammed Nafees
2025-10-30 19:05:02 +05:30
committed by GitHub
parent 745918ba2c
commit 91cdb28ddf
8 changed files with 266 additions and 176 deletions
@@ -7,6 +7,10 @@ readiness:
description: Healthy
"500":
description: Not ready to accept traffic
content:
application/json:
schema:
$ref: "../../components/schemas/_index.yaml#/APIErrors"
security: []
summary: Get readiness
tags:
@@ -20,6 +24,10 @@ liveness:
description: Healthy
"500":
description: Not liveness
content:
application/json:
schema:
$ref: "../../components/schemas/_index.yaml#/APIErrors"
security: []
summary: Get liveness
tags:
+65 -14
View File
@@ -1,41 +1,92 @@
package metadata
import (
"context"
"errors"
"fmt"
"time"
"github.com/labstack/echo/v4"
"github.com/hatchet-dev/hatchet/api/v1/server/oas/gen"
)
func (u *MetadataService) LivenessGet(ctx echo.Context, request gen.LivenessGetRequestObject) (gen.LivenessGetResponseObject, error) {
if !u.config.APIRepository.Health().IsHealthy() {
return nil, fmt.Errorf("api repository is not healthy")
func (u *MetadataService) collectHealthErrors(ctx context.Context) []error {
errs := []error{}
if !u.config.APIRepository.Health().IsHealthy(ctx) {
errs = append(errs, errors.New("api repository is not healthy"))
}
if !u.config.EngineRepository.Health().IsHealthy() {
return nil, fmt.Errorf("engine repository is not healthy")
if !u.config.EngineRepository.Health().IsHealthy(ctx) {
errs = append(errs, errors.New("engine repository is not healthy"))
}
if !u.config.MessageQueue.IsReady() {
return nil, fmt.Errorf("task queue is not healthy")
errs = append(errs, errors.New("task queue is not healthy"))
}
return errs
}
func (u *MetadataService) logHealthErrors(errs []error) {
for _, err := range errs {
u.config.Logger.Err(err).Msg("health check failed")
}
}
func (u *MetadataService) LivenessGet(ctx echo.Context, request gen.LivenessGetRequestObject) (gen.LivenessGetResponseObject, error) {
gCtx, cancel := context.WithTimeout(ctx.Request().Context(), 3*time.Second)
defer cancel()
allErrors := u.collectHealthErrors(gCtx)
if len(allErrors) > 0 {
u.logHealthErrors(allErrors)
allErrors = append(allErrors, fmt.Errorf(
"pg connections - acquired: %d, idle: %d, total: %d",
u.config.APIRepository.Health().PgStat().AcquiredConns(),
u.config.APIRepository.Health().PgStat().IdleConns(),
u.config.APIRepository.Health().PgStat().TotalConns(),
))
return gen.LivenessGet500JSONResponse(gen.APIErrors{Errors: errorsToAPIErrors(allErrors)}), nil
}
return gen.LivenessGet200Response{}, nil
}
func (u *MetadataService) ReadinessGet(ctx echo.Context, request gen.ReadinessGetRequestObject) (gen.ReadinessGetResponseObject, error) {
if !u.config.APIRepository.Health().IsHealthy() {
return nil, fmt.Errorf("api repository is not healthy")
}
gCtx, cancel := context.WithTimeout(ctx.Request().Context(), 3*time.Second)
defer cancel()
if !u.config.EngineRepository.Health().IsHealthy() {
return nil, fmt.Errorf("engine repository is not healthy")
}
allErrors := u.collectHealthErrors(gCtx)
if !u.config.MessageQueue.IsReady() {
return nil, fmt.Errorf("task queue is not healthy")
if len(allErrors) > 0 {
u.logHealthErrors(allErrors)
allErrors = append(allErrors, fmt.Errorf(
"pg connections - acquired: %d, idle: %d, total: %d",
u.config.APIRepository.Health().PgStat().AcquiredConns(),
u.config.APIRepository.Health().PgStat().IdleConns(),
u.config.APIRepository.Health().PgStat().TotalConns(),
))
return gen.ReadinessGet500JSONResponse(gen.APIErrors{Errors: errorsToAPIErrors(allErrors)}), nil
}
return gen.ReadinessGet200Response{}, nil
}
func errorsToAPIErrors(errors []error) []gen.APIError {
apiErrors := make([]gen.APIError, len(errors))
for i, err := range errors {
apiErrors[i] = gen.APIError{
Description: err.Error(),
}
}
return apiErrors
}
+154 -152
View File
@@ -7067,12 +7067,13 @@ func (response LivenessGet200Response) VisitLivenessGetResponse(w http.ResponseW
return nil
}
type LivenessGet500Response struct {
}
type LivenessGet500JSONResponse APIErrors
func (response LivenessGet500Response) VisitLivenessGetResponse(w http.ResponseWriter) error {
func (response LivenessGet500JSONResponse) VisitLivenessGetResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
return nil
return json.NewEncoder(w).Encode(response)
}
type ReadinessGetRequestObject struct {
@@ -7090,12 +7091,13 @@ func (response ReadinessGet200Response) VisitReadinessGetResponse(w http.Respons
return nil
}
type ReadinessGet500Response struct {
}
type ReadinessGet500JSONResponse APIErrors
func (response ReadinessGet500Response) VisitReadinessGetResponse(w http.ResponseWriter) error {
func (response ReadinessGet500JSONResponse) VisitReadinessGetResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
return nil
return json.NewEncoder(w).Encode(response)
}
type AlertEmailGroupDeleteRequestObject struct {
@@ -15622,150 +15624,150 @@ var swaggerSpec = []string{
"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",
"KGZamkwNAwA=",
"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",
"/8W8jFj0DQMA",
}
// GetSwagger returns the content of the embedded swagger specification file
+2 -2
View File
@@ -1016,7 +1016,7 @@ export class Api<
* @request GET:/api/ready
*/
readinessGet = (params: RequestParams = {}) =>
this.request<void, void>({
this.request<void, APIErrors>({
path: `/api/ready`,
method: "GET",
...params,
@@ -1030,7 +1030,7 @@ export class Api<
* @request GET:/api/live
*/
livenessGet = (params: RequestParams = {}) =>
this.request<void, void>({
this.request<void, APIErrors>({
path: `/api/live`,
method: "GET",
...params,
+5 -2
View File
@@ -36,8 +36,11 @@ func (h *Health) SetReady(ready bool) {
func (h *Health) Start(port int) (func() error, error) {
mux := http.NewServeMux()
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
mux.HandleFunc("/live", func(w http.ResponseWriter, r *http.Request) {
if !h.ready || !h.queue.IsReady() || !h.repository.Health().IsHealthy() {
if !h.ready || !h.queue.IsReady() || !h.repository.Health().IsHealthy(ctx) {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
@@ -46,7 +49,7 @@ func (h *Health) Start(port int) (func() error, error) {
})
mux.HandleFunc("/ready", func(w http.ResponseWriter, r *http.Request) {
if !h.ready || !h.queue.IsReady() || !h.repository.Health().IsHealthy() {
if !h.ready || !h.queue.IsReady() || !h.repository.Health().IsHealthy(ctx) {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
+22
View File
@@ -13044,6 +13044,7 @@ type ClientWithResponsesInterface interface {
type LivenessGetResponse struct {
Body []byte
HTTPResponse *http.Response
JSON500 *APIErrors
}
// Status returns HTTPResponse.Status
@@ -13065,6 +13066,7 @@ func (r LivenessGetResponse) StatusCode() int {
type ReadinessGetResponse struct {
Body []byte
HTTPResponse *http.Response
JSON500 *APIErrors
}
// Status returns HTTPResponse.Status
@@ -17633,6 +17635,16 @@ func ParseLivenessGetResponse(rsp *http.Response) (*LivenessGetResponse, error)
HTTPResponse: rsp,
}
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500:
var dest APIErrors
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON500 = &dest
}
return response, nil
}
@@ -17649,6 +17661,16 @@ func ParseReadinessGetResponse(rsp *http.Response) (*ReadinessGetResponse, error
HTTPResponse: rsp,
}
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500:
var dest APIErrors
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
response.JSON500 = &dest
}
return response, nil
}
+6 -2
View File
@@ -1,8 +1,12 @@
package repository
import "github.com/jackc/pgx/v5/pgxpool"
import (
"context"
"github.com/jackc/pgx/v5/pgxpool"
)
type HealthRepository interface {
IsHealthy() bool
IsHealthy(ctx context.Context) bool
PgStat() *pgxpool.Stat
}
+4 -4
View File
@@ -19,8 +19,8 @@ func NewHealthAPIRepository(shared *sharedRepository) repository.HealthRepositor
}
}
func (a *healthAPIRepository) IsHealthy() bool {
_, err := a.queries.Health(context.Background(), a.pool)
func (a *healthAPIRepository) IsHealthy(ctx context.Context) bool {
_, err := a.queries.Health(ctx, a.pool)
if err != nil { //nolint:gosimple
return false
@@ -48,8 +48,8 @@ func NewHealthEngineRepository(pool *pgxpool.Pool) repository.HealthRepository {
}
}
func (a *healthEngineRepository) IsHealthy() bool {
_, err := a.queries.Health(context.Background(), a.pool)
func (a *healthEngineRepository) IsHealthy(ctx context.Context) bool {
_, err := a.queries.Health(ctx, a.pool)
if err != nil { //nolint:gosimple
return false