diff --git a/checker.go b/checker.go index e604264..3b67945 100644 --- a/checker.go +++ b/checker.go @@ -1,20 +1,21 @@ package health import ( + "context" "sync" ) // Checker is a interface used to provide an indication of application health. type Checker interface { - Check() Health + Check(ctx context.Context) Health } // CheckerFunc is an adapter to allow the use of // ordinary go functions as Checkers. -type CheckerFunc func() Health +type CheckerFunc func(ctx context.Context) Health -func (f CheckerFunc) Check() Health { - return f() +func (f CheckerFunc) Check(ctx context.Context) Health { + return f(ctx) } type checkerItem struct { @@ -51,7 +52,7 @@ func (c *CompositeChecker) AddChecker(name string, checker Checker) { // Check returns the combination of all checkers added // if some check is not up, the combined is marked as down -func (c CompositeChecker) Check() Health { +func (c CompositeChecker) Check(ctx context.Context) Health { health := NewHealth() health.Up() @@ -67,7 +68,7 @@ func (c CompositeChecker) Check() Health { wg.Add(1) item := item go func() { - ch <- state{h: item.checker.Check(), name: item.name} + ch <- state{h: item.checker.Check(ctx), name: item.name} wg.Done() }() } diff --git a/checker_test.go b/checker_test.go index d34f8f9..5b7b596 100644 --- a/checker_test.go +++ b/checker_test.go @@ -1,10 +1,13 @@ package health -import "testing" +import ( + "context" + "testing" +) type outOfServiceTestChecker struct{} -func (c outOfServiceTestChecker) Check() Health { +func (c outOfServiceTestChecker) Check(ctx context.Context) Health { health := NewHealth() health.OutOfService() @@ -13,7 +16,7 @@ func (c outOfServiceTestChecker) Check() Health { type upTestChecker struct{} -func (c upTestChecker) Check() Health { +func (c upTestChecker) Check(ctx context.Context) Health { health := NewHealth() health.Up() @@ -22,7 +25,7 @@ func (c upTestChecker) Check() Health { type downTestChecker struct{} -func (c downTestChecker) Check() Health { +func (c downTestChecker) Check(ctx context.Context) Health { health := NewHealth() health.Down() @@ -47,7 +50,7 @@ func Test_CompositeChecker_Check_Up(t *testing.T) { c := NewCompositeChecker() c.AddChecker("upTestChecker", upTestChecker{}) - health := c.Check() + health := c.Check(context.Background()) if !health.IsUp() { t.Errorf("health.IsUp() == %t, wants %t", health.IsUp(), true) @@ -58,7 +61,7 @@ func Test_CompositeChecker_Check_Down(t *testing.T) { c := NewCompositeChecker() c.AddChecker("downTestChecker", downTestChecker{}) - health := c.Check() + health := c.Check(context.Background()) if !health.IsDown() { t.Errorf("health.IsDown() == %t, wants %t", health.IsDown(), true) @@ -69,7 +72,7 @@ func Test_CompositeChecker_Check_OutOfService(t *testing.T) { c := NewCompositeChecker() c.AddChecker("outOfServiceTestChecker", outOfServiceTestChecker{}) - health := c.Check() + health := c.Check(context.Background()) if !health.IsDown() { t.Errorf("health.IsDown() == %t, wants %t", health.IsDown(), true) @@ -81,7 +84,7 @@ func Test_CompositeChecker_Check_Down_combined(t *testing.T) { c.AddChecker("downTestChecker", downTestChecker{}) c.AddChecker("upTestChecker", upTestChecker{}) - health := c.Check() + health := c.Check(context.Background()) if !health.IsDown() { t.Errorf("health.IsDown() == %t, wants %t", health.IsDown(), true) @@ -93,7 +96,7 @@ func Test_CompositeChecker_Check_Up_combined(t *testing.T) { c.AddChecker("upTestChecker", upTestChecker{}) c.AddChecker("upTestChecker", upTestChecker{}) - health := c.Check() + health := c.Check(context.Background()) if !health.IsUp() { t.Errorf("health.IsUp() == %t, wants %t", health.IsUp(), true) @@ -125,14 +128,14 @@ func Test_CompositeChecker_AddInfo_null_map(t *testing.T) { } func TestCheckerFunc_Check(t *testing.T) { - f := CheckerFunc(func() Health { + f := CheckerFunc(func(ctx context.Context) Health { h := NewHealth() h.Up() return h }) - h := f.Check() + h := f.Check(context.Background()) if !h.IsUp() { t.Errorf("h.IsUp() == %t, wants %t", h.IsUp(), true) diff --git a/handler.go b/handler.go index 7e39e12..eea5a08 100644 --- a/handler.go +++ b/handler.go @@ -20,7 +20,7 @@ func NewHandler() Handler { func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") - health := h.CompositeChecker.Check() + health := h.CompositeChecker.Check(r.Context()) if health.IsDown() { w.WriteHeader(http.StatusServiceUnavailable) diff --git a/url/checker.go b/url/checker.go index 45a1161..9e394c4 100644 --- a/url/checker.go +++ b/url/checker.go @@ -1,39 +1,39 @@ package url import ( + "context" "net/http" - "time" "github.com/dimiro1/health" ) // Checker is a checker that check a given URL type Checker struct { - URL string - Timeout time.Duration + URL string } // NewChecker returns a new url.Checker with the given URL func NewChecker(url string) Checker { - return Checker{URL: url, Timeout: 5 * time.Second} -} - -// NewCheckerWithTimeout returns a new url.Checker with the given URL and given timeout -func NewCheckerWithTimeout(url string, timeout time.Duration) Checker { - return Checker{URL: url, Timeout: timeout} + return Checker{URL: url} } // Check makes a HEAD request to the given URL // If the request returns something different than StatusOK, // The status is set to StatusBadRequest and the URL is considered Down -func (u Checker) Check() health.Health { - client := http.Client{ - Timeout: u.Timeout, +func (u Checker) Check(ctx context.Context) health.Health { + health := health.NewHealth() + + req, err := http.NewRequest("HEAD", u.URL, nil) + if err != nil { + health.Down().AddInfo("code", http.StatusBadRequest) + return health } - health := health.NewHealth() + req = req.WithContext(ctx) - resp, err := client.Head(u.URL) + client := http.Client{} + + resp, err := client.Do(req) if resp != nil { defer resp.Body.Close() @@ -41,7 +41,6 @@ func (u Checker) Check() health.Health { if err != nil { health.Down().AddInfo("code", http.StatusBadRequest) - return health } diff --git a/url/checker_test.go b/url/checker_test.go index 4775649..cfd5491 100644 --- a/url/checker_test.go +++ b/url/checker_test.go @@ -7,26 +7,10 @@ import ( "net/http/httptest" "strings" "testing" - "time" "github.com/dimiro1/health" ) -func Test_NewCheckerWithTimeout(t *testing.T) { - timeout := 2 * time.Second - url := "http://www.google.com/" - - c := NewCheckerWithTimeout(url, timeout) - - if c.Timeout != timeout { - t.Errorf("NewCheckerWithTimeout().Timeout == %d, wants %d", c.Timeout, timeout) - } - - if c.URL != url { - t.Errorf("NewCheckerWithTimeout().URL == %s, wants %s", c.URL, url) - } -} - func Test_Checker_Check_Up(t *testing.T) { mux := http.NewServeMux()