Update TwiN/health to v1.3.0

This commit is contained in:
TwiN
2021-11-19 23:43:24 -05:00
parent c6d0809ecc
commit 5877c4b2be
5 changed files with 66 additions and 28 deletions

View File

@ -33,16 +33,24 @@ If you prefer using JSON, however, you may initialize the health handler like so
```go
router.Handle("/health", health.Handler().WithJSON(true))
```
The above will cause the response body to become `{"status":"UP"}` and `{"status":"DOWN"}` for both status respectively.
The above will cause the response body to become `{"status":"UP"}` and `{"status":"DOWN"}` for both status respectively,
unless there is a reason, in which case a reason set to `because` would return `{"status":"UP", "reason":"because"}`
and `{"status":"DOWN", "reason":"because"}` respectively.
To change the health of the application, you can use `health.SetStatus(<status>)` where `<status>` is one `health.Up`
or `health.Down`:
```go
health.SetStatus(health.Up)
health.SetStatus(health.Down)
```
As for the reason:
```go
health.SetReason("database is unreachable")
```
Generally speaking, you'd only want to include a reason if the status is `Down`, but you can do as you desire.
### Complete example
```go

View File

@ -1,6 +1,7 @@
package health
import (
"encoding/json"
"net/http"
"sync"
)
@ -12,12 +13,20 @@ var (
}
)
type responseBody struct {
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
}
// healthHandler is the HTTP handler for serving the health endpoint
type healthHandler struct {
useJSON bool
status Status
useJSON bool
resetReasonOnUp bool
sync.RWMutex
status Status
reason string
mutex sync.RWMutex
}
// WithJSON configures whether the handler should output a response in JSON or in raw text
@ -32,34 +41,29 @@ func (h *healthHandler) WithJSON(v bool) *healthHandler {
func (h *healthHandler) ServeHTTP(writer http.ResponseWriter, _ *http.Request) {
var statusCode int
var body []byte
handlerStatus := h.getStatus()
if handlerStatus == Up {
h.mutex.RLock()
status, reason, useJSON := h.status, h.reason, h.useJSON
h.mutex.RUnlock()
if status == Up {
statusCode = http.StatusOK
} else {
statusCode = http.StatusInternalServerError
}
if h.useJSON {
if useJSON {
// We can safely ignore the error here because we know that both values are strings, therefore are supported encoders.
body, _ = json.Marshal(responseBody{Status: string(status), Reason: reason})
writer.Header().Set("Content-Type", "application/json")
body = []byte(`{"status":"` + handlerStatus + `"}`)
} else {
body = []byte(handlerStatus)
if len(reason) == 0 {
body = []byte(status)
} else {
body = []byte(string(status) + ": " + reason)
}
}
writer.WriteHeader(statusCode)
_, _ = writer.Write(body)
}
func (h *healthHandler) getStatus() Status {
h.Lock()
defer h.Unlock()
return h.status
}
func (h *healthHandler) setStatus(status Status) {
h.Lock()
h.status = status
h.Unlock()
}
// Handler retrieves the health handler
func Handler() *healthHandler {
return handler
@ -67,10 +71,36 @@ func Handler() *healthHandler {
// GetStatus retrieves the current status returned by the health handler
func GetStatus() Status {
return handler.getStatus()
handler.mutex.RLock()
defer handler.mutex.RUnlock()
return handler.status
}
// SetStatus sets the status to be returned by the health handler
func SetStatus(status Status) {
handler.setStatus(status)
handler.mutex.Lock()
handler.status = status
handler.mutex.Unlock()
}
// GetReason retrieves the current status returned by the health handler
func GetReason() string {
handler.mutex.RLock()
defer handler.mutex.RUnlock()
return handler.reason
}
// SetReason sets a reason for the current status to be returned by the health handler
func SetReason(reason string) {
handler.mutex.Lock()
handler.reason = reason
handler.mutex.Unlock()
}
// SetStatusAndReason sets the status and reason to be returned by the health handler
func SetStatusAndReason(status Status, reason string) {
handler.mutex.Lock()
handler.status = status
handler.reason = reason
handler.mutex.Unlock()
}