github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/healthz/health.go (about) 1 package healthz 2 3 import ( 4 "context" 5 "net/http" 6 7 "github.com/kyma-incubator/compass/components/director/pkg/log" 8 "github.com/pkg/errors" 9 ) 10 11 const ( 12 // UP missing godoc 13 UP = "UP" 14 // DOWN missing godoc 15 DOWN = "DOWN" 16 ) 17 18 // Health missing godoc 19 type Health struct { 20 ctx context.Context 21 indicators []Indicator 22 config map[string]IndicatorConfig 23 } 24 25 // New returns new health with the given context 26 func New(ctx context.Context, healthCfg Config) (*Health, error) { 27 if err := healthCfg.Validate(); err != nil { 28 return nil, errors.Wrap(err, "An error has occurred while validating indicator config") 29 } 30 31 cfg := make(map[string]IndicatorConfig) 32 for _, i := range healthCfg.Indicators { 33 cfg[i.Name] = i 34 } 35 36 return &Health{ 37 ctx: ctx, 38 config: cfg, 39 indicators: make([]Indicator, 0), 40 }, nil 41 } 42 43 // RegisterIndicator registers the provided indicator - if configuration for indicator with the same name is present, 44 // it is used, otherwise a default indicator configuration is used 45 func (h *Health) RegisterIndicator(ind Indicator) *Health { 46 cfg, ok := h.config[ind.Name()] 47 if !ok { 48 cfg = NewDefaultConfig() 49 } 50 ind.Configure(cfg) 51 52 h.indicators = append(h.indicators, ind) 53 return h 54 } 55 56 // Start will start all of the defined indicators. 57 // Each of the indicators run in their own goroutines 58 func (h *Health) Start() *Health { 59 for _, ind := range h.indicators { 60 ind.Run(h.ctx) 61 } 62 return h 63 } 64 65 // ReportStatus reports the status of all the indicators 66 func (h *Health) ReportStatus() string { 67 state := UP 68 for _, ind := range h.indicators { 69 status := ind.Status() 70 if status.Error() != nil { 71 state = DOWN 72 log.C(h.ctx).Errorf("Reporting status DOWN for indicator: %s, error: %s, details: %s", ind.Name(), status.Error(), status.Details()) 73 } 74 } 75 76 return state 77 } 78 79 // NewHealthHandler returns new health handler func with the provided health instance 80 func NewHealthHandler(h *Health) func(writer http.ResponseWriter, request *http.Request) { 81 return func(writer http.ResponseWriter, request *http.Request) { 82 responseCode := http.StatusOK 83 84 state := h.ReportStatus() 85 if state == DOWN { 86 responseCode = http.StatusInternalServerError 87 } 88 89 writer.WriteHeader(responseCode) 90 if _, err := writer.Write([]byte(state)); err != nil { 91 log.C(request.Context()).WithError(err).Errorf("An error has occurred while writing to response body: %v", err) 92 } 93 } 94 }