Adding upstream version 1.6.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
ea7b92a91b
commit
9412e3a223
13 changed files with 568 additions and 0 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* text=auto eol=lf
|
3
.github/codecov.yml
vendored
Normal file
3
.github/codecov.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
patch: off
|
15
.github/dependabot.yml
vendored
Normal file
15
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
labels: ["dependencies"]
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
day: "sunday"
|
||||||
|
- package-ecosystem: "gomod"
|
||||||
|
directory: "/"
|
||||||
|
open-pull-requests-limit: 1
|
||||||
|
labels: ["dependencies"]
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
day: "sunday"
|
30
.github/workflows/test.yml
vendored
Normal file
30
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
name: test
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '*.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths-ignore:
|
||||||
|
- '*.md'
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 3
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Benchmark
|
||||||
|
run: go test -bench . -race
|
||||||
|
- name: Test (race)
|
||||||
|
run: go test -mod vendor ./... -race
|
||||||
|
- name: Test (coverage)
|
||||||
|
run: go test -mod vendor ./... -coverprofile=coverage.txt -covermode=atomic
|
||||||
|
- name: Codecov
|
||||||
|
uses: codecov/codecov-action@v3.1.1
|
||||||
|
with:
|
||||||
|
files: ./coverage.txt
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.idea
|
||||||
|
*.iml
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 TwiN
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
bench:
|
||||||
|
go test -bench . -race
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test . -race
|
92
README.md
Normal file
92
README.md
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# health
|
||||||
|

|
||||||
|
[](https://goreportcard.com/report/github.com/TwiN/health)
|
||||||
|
[](https://codecov.io/gh/TwiN/health)
|
||||||
|
[](https://github.com/TwiN/health)
|
||||||
|
[](https://pkg.go.dev/github.com/TwiN/health)
|
||||||
|
|
||||||
|
Health is a library used for creating a very simple health endpoint.
|
||||||
|
|
||||||
|
While implementing a health endpoint is very simple, I've grown tired of implementing
|
||||||
|
it over and over again.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
```console
|
||||||
|
go get -u github.com/TwiN/health
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
To retrieve the handler, you must use `health.Handler()` and are expected to pass it to the router like so:
|
||||||
|
```go
|
||||||
|
router := http.NewServeMux()
|
||||||
|
router.Handle("/health", health.Handler())
|
||||||
|
server := &http.Server{
|
||||||
|
Addr: ":8080",
|
||||||
|
Handler: router,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the handler will return `UP` when the status is up, and `DOWN` when the status is down.
|
||||||
|
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,
|
||||||
|
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 set the health status to `DOWN` with a reason:
|
||||||
|
```go
|
||||||
|
health.SetUnhealthy("<enter reason here>")
|
||||||
|
```
|
||||||
|
The string passed will be automatically set as the reason.
|
||||||
|
|
||||||
|
In a similar fashion, to set the health status to `UP` and clear the reason:
|
||||||
|
```go
|
||||||
|
health.SetHealthy()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Alternatively, to set the status and the reason individually you can use `health.SetStatus(<status>)` where `<status>` is `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.
|
||||||
|
|
||||||
|
For the sake of convenience, you can also use `health.SetStatusAndReason(<status>, <reason>)` instead of doing
|
||||||
|
`health.SetStatus(<status>)` and `health.SetReason(<reason>)` separately.
|
||||||
|
|
||||||
|
|
||||||
|
### Complete example
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/TwiN/health"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
router := http.NewServeMux()
|
||||||
|
router.Handle("/health", health.Handler())
|
||||||
|
server := &http.Server{
|
||||||
|
Addr: "0.0.0.0:8080",
|
||||||
|
Handler: router,
|
||||||
|
ReadTimeout: 15 * time.Second,
|
||||||
|
WriteTimeout: 15 * time.Second,
|
||||||
|
IdleTimeout: 15 * time.Second,
|
||||||
|
}
|
||||||
|
server.ListenAndServe()
|
||||||
|
}
|
||||||
|
```
|
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/TwiN/health
|
||||||
|
|
||||||
|
go 1.19
|
142
health.go
Normal file
142
health.go
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
package health
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
handler = &healthHandler{
|
||||||
|
useJSON: false,
|
||||||
|
status: Up,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// responseBody is the body of the response returned by the health handler.
|
||||||
|
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
|
||||||
|
reason string
|
||||||
|
|
||||||
|
mutex sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithJSON configures whether the handler should output a response in JSON or in raw text
|
||||||
|
//
|
||||||
|
// Defaults to false
|
||||||
|
func (h *healthHandler) WithJSON(v bool) *healthHandler {
|
||||||
|
h.useJSON = v
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP serves the HTTP request for the health handler
|
||||||
|
func (h *healthHandler) ServeHTTP(writer http.ResponseWriter, _ *http.Request) {
|
||||||
|
statusCode, body, useJSON := h.getResponseStatusCodeAndBodyAndWhetherBodyUsesJSON()
|
||||||
|
if useJSON {
|
||||||
|
writer.Header().Set("Content-Type", "application/json")
|
||||||
|
}
|
||||||
|
writer.WriteHeader(statusCode)
|
||||||
|
_, _ = writer.Write(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *healthHandler) GetResponseStatusCodeAndBody() (statusCode int, body []byte) {
|
||||||
|
statusCode, body, _ = h.getResponseStatusCodeAndBodyAndWhetherBodyUsesJSON()
|
||||||
|
return statusCode, body
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *healthHandler) getResponseStatusCodeAndBodyAndWhetherBodyUsesJSON() (statusCode int, body []byte, useJSON bool) {
|
||||||
|
var status Status
|
||||||
|
var reason string
|
||||||
|
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 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})
|
||||||
|
} else {
|
||||||
|
if len(reason) == 0 {
|
||||||
|
body = []byte(status)
|
||||||
|
} else {
|
||||||
|
body = []byte(string(status) + ": " + reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler retrieves the health handler
|
||||||
|
func Handler() *healthHandler {
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatus retrieves the current status returned by the health handler
|
||||||
|
func GetStatus() Status {
|
||||||
|
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.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()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatusAndResetReason sets the status and resets the reason to a blank string
|
||||||
|
func SetStatusAndResetReason(status Status) {
|
||||||
|
handler.mutex.Lock()
|
||||||
|
handler.status = status
|
||||||
|
handler.reason = ""
|
||||||
|
handler.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHealthy sets the status to Up and the reason to a blank string
|
||||||
|
func SetHealthy() {
|
||||||
|
SetStatusAndResetReason(Up)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUnhealthy sets the status to Down and the reason to the string passed as parameter
|
||||||
|
//
|
||||||
|
// Unlike SetHealthy, this function enforces setting a reason, because it's good practice to give at least a bit
|
||||||
|
// of information as to why an application is unhealthy, and this library attempts to promote good practices.
|
||||||
|
func SetUnhealthy(reason string) {
|
||||||
|
handler.mutex.Lock()
|
||||||
|
handler.status = Down
|
||||||
|
handler.reason = reason
|
||||||
|
handler.mutex.Unlock()
|
||||||
|
}
|
27
health_bench_test.go
Normal file
27
health_bench_test.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package health_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TwiN/health"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkHealthHandler_ServeHTTP(b *testing.B) {
|
||||||
|
h := health.Handler().WithJSON(true)
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
request, _ := http.NewRequest("GET", "/health", http.NoBody)
|
||||||
|
responseRecorder := httptest.NewRecorder()
|
||||||
|
h.ServeHTTP(responseRecorder, request)
|
||||||
|
if n := rand.Intn(100); n < 1 {
|
||||||
|
health.SetStatus(health.Down)
|
||||||
|
} else if n < 5 {
|
||||||
|
health.SetStatus(health.Up)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b.ReportAllocs()
|
||||||
|
}
|
219
health_test.go
Normal file
219
health_test.go
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
package health_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TwiN/health"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHealthHandler_ServeHTTP(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
type Scenario struct {
|
||||||
|
Name string
|
||||||
|
useJSON bool
|
||||||
|
status health.Status
|
||||||
|
reason string
|
||||||
|
expectedResponseBody string
|
||||||
|
expectedResponseCode int
|
||||||
|
}
|
||||||
|
scenarios := []Scenario{
|
||||||
|
{
|
||||||
|
Name: "text-up",
|
||||||
|
useJSON: false,
|
||||||
|
status: health.Up,
|
||||||
|
expectedResponseBody: "UP",
|
||||||
|
expectedResponseCode: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "text-up-reason",
|
||||||
|
useJSON: false,
|
||||||
|
status: health.Up,
|
||||||
|
reason: "reason",
|
||||||
|
expectedResponseBody: "UP: reason",
|
||||||
|
expectedResponseCode: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "text-down",
|
||||||
|
useJSON: false,
|
||||||
|
status: health.Down,
|
||||||
|
expectedResponseBody: "DOWN",
|
||||||
|
expectedResponseCode: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "text-down-reason",
|
||||||
|
useJSON: false,
|
||||||
|
status: health.Down,
|
||||||
|
reason: "reason",
|
||||||
|
expectedResponseBody: "DOWN: reason",
|
||||||
|
expectedResponseCode: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "json-up",
|
||||||
|
useJSON: true,
|
||||||
|
status: health.Up,
|
||||||
|
expectedResponseBody: `{"status":"UP"}`,
|
||||||
|
expectedResponseCode: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "json-up-reason",
|
||||||
|
useJSON: true,
|
||||||
|
status: health.Up,
|
||||||
|
reason: "Error",
|
||||||
|
expectedResponseBody: `{"status":"UP","reason":"Error"}`,
|
||||||
|
expectedResponseCode: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "json-down",
|
||||||
|
useJSON: true,
|
||||||
|
status: health.Down,
|
||||||
|
expectedResponseBody: `{"status":"DOWN"}`,
|
||||||
|
expectedResponseCode: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "json-down-reason",
|
||||||
|
useJSON: true,
|
||||||
|
status: health.Down,
|
||||||
|
reason: "Error",
|
||||||
|
expectedResponseBody: `{"status":"DOWN","reason":"Error"}`,
|
||||||
|
expectedResponseCode: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "json-down-reason-with-quotes",
|
||||||
|
useJSON: true,
|
||||||
|
status: health.Down,
|
||||||
|
reason: `error "with" quotes`,
|
||||||
|
expectedResponseBody: `{"status":"DOWN","reason":"error \"with\" quotes"}`,
|
||||||
|
expectedResponseCode: 500,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(scenario.Name, func(t *testing.T) {
|
||||||
|
handler := health.Handler().WithJSON(scenario.useJSON)
|
||||||
|
health.SetStatus(scenario.status)
|
||||||
|
health.SetReason(scenario.reason)
|
||||||
|
|
||||||
|
request, _ := http.NewRequest("GET", "/health", http.NoBody)
|
||||||
|
responseRecorder := httptest.NewRecorder()
|
||||||
|
|
||||||
|
handler.ServeHTTP(responseRecorder, request)
|
||||||
|
if responseRecorder.Code != scenario.expectedResponseCode {
|
||||||
|
t.Errorf("expected GET /health to return status code %d, got %d", scenario.expectedResponseCode, responseRecorder.Code)
|
||||||
|
}
|
||||||
|
body, _ := io.ReadAll(responseRecorder.Body)
|
||||||
|
if string(body) != scenario.expectedResponseBody {
|
||||||
|
t.Errorf("expected GET /health to return %s, got %s", scenario.expectedResponseBody, string(body))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHealthHandler_GetResponseStatusCodeAndBody(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
handler := health.Handler().WithJSON(true)
|
||||||
|
health.SetStatus(health.Up)
|
||||||
|
|
||||||
|
statusCode, body := handler.GetResponseStatusCodeAndBody()
|
||||||
|
if statusCode != 200 {
|
||||||
|
t.Error("expected status code to be 200, got", statusCode)
|
||||||
|
}
|
||||||
|
if string(body) != `{"status":"UP"}` {
|
||||||
|
t.Error("expected body to be {\"status\":\"UP\"}, got", string(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetStatus(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetStatus(health.Up)
|
||||||
|
if health.GetStatus() != health.Up {
|
||||||
|
t.Error("expected status to be 'Up', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
health.SetStatus(health.Down)
|
||||||
|
if health.GetStatus() != health.Down {
|
||||||
|
t.Error("expected status to be 'Down', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
health.SetStatus(health.Up)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetReason(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetReason("hello")
|
||||||
|
if health.GetReason() != "hello" {
|
||||||
|
t.Error("expected reason to be 'hello', got", health.GetReason())
|
||||||
|
}
|
||||||
|
health.SetReason("world")
|
||||||
|
if health.GetReason() != "world" {
|
||||||
|
t.Error("expected reason to be 'world', got", health.GetReason())
|
||||||
|
}
|
||||||
|
health.SetReason("")
|
||||||
|
if health.GetReason() != "" {
|
||||||
|
t.Error("expected reason to be '', got", health.GetReason())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetStatusAndReason(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetStatusAndReason(health.Down, "for what")
|
||||||
|
if health.GetStatus() != health.Down {
|
||||||
|
t.Error("expected status to be 'Down', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "for what" {
|
||||||
|
t.Error("expected reason to be 'hello', got", health.GetReason())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetStatusAndResetReason(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetStatusAndReason(health.Down, "for what")
|
||||||
|
if health.GetStatus() != health.Down {
|
||||||
|
t.Error("expected status to be 'Down', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "for what" {
|
||||||
|
t.Error("expected reason to be 'for what', got", health.GetReason())
|
||||||
|
}
|
||||||
|
health.SetStatusAndResetReason(health.Up)
|
||||||
|
if health.GetStatus() != health.Up {
|
||||||
|
t.Error("expected status to be 'Up', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "" {
|
||||||
|
t.Error("expected reason to be '', got", health.GetReason())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetHealthy(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetStatusAndReason(health.Down, "for what")
|
||||||
|
if health.GetStatus() != health.Down {
|
||||||
|
t.Error("expected status to be 'Down', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "for what" {
|
||||||
|
t.Error("expected reason to be 'for what', got", health.GetReason())
|
||||||
|
}
|
||||||
|
health.SetHealthy()
|
||||||
|
if health.GetStatus() != health.Up {
|
||||||
|
t.Error("expected status to be 'Up', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "" {
|
||||||
|
t.Error("expected reason to be '', got", health.GetReason())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetUnhealthy(t *testing.T) {
|
||||||
|
defer health.SetHealthy()
|
||||||
|
health.SetStatusAndReason(health.Up, "")
|
||||||
|
if health.GetStatus() != health.Up {
|
||||||
|
t.Error("expected status to be '', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "" {
|
||||||
|
t.Error("expected reason to be '', got", health.GetReason())
|
||||||
|
}
|
||||||
|
health.SetUnhealthy("for what")
|
||||||
|
if health.GetStatus() != health.Down {
|
||||||
|
t.Error("expected status to be 'Down', got", health.GetStatus())
|
||||||
|
}
|
||||||
|
if health.GetReason() != "for what" {
|
||||||
|
t.Error("expected reason to be 'for what', got", health.GetReason())
|
||||||
|
}
|
||||||
|
}
|
8
status.go
Normal file
8
status.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package health
|
||||||
|
|
||||||
|
type Status string
|
||||||
|
|
||||||
|
var (
|
||||||
|
Down Status = "DOWN" // For when the application is unhealthy
|
||||||
|
Up Status = "UP" // For when the application is healthy
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue