diff --git a/checkers/README.md b/checkers/README.md index ec8338c..230f8f1 100644 --- a/checkers/README.md +++ b/checkers/README.md @@ -5,7 +5,7 @@ types of dependencies. If a pre-built checker is not available, you can create your own checkers by implementing the `ICheckable` interface (which consists of a single method - -`Status() (interface{}, error)`). +`Status(context.Context) (interface{}, error)`). If you do create a custom-checker - consider opening a PR and adding it to the list of built-in checkers. @@ -44,17 +44,19 @@ The SQL DB checker has implementations for the following interfaces: - `SQLExecer`, which encloses `ExecContext` in [`sql.DB`](https://golang.org/pkg/database/sql/#DB.ExecContext), [`sql.Conn`](https://golang.org/pkg/database/sql/#Conn.ExecContext), [`sql.Stmt`](https://golang.org/pkg/database/sql/#Stmt.ExecContext), and [`sql.Tx`](https://golang.org/pkg/database/sql/#Tx.ExecContext) #### SQLConfig -The `SQLConfig` struct is required when using the SQL DB health check. It **must** contain an inplementation of one of either `SQLPinger`, `SQLQueryer`, or `SQLExecer`. + +The `SQLConfig` struct is required when using the SQL DB health check. It **must** contain an inplementation of one of either `SQLPinger`, `SQLQueryer`, or `SQLExecer`. If `SQLQueryer` or `SQLExecer` are implemented, then `Query` must be valid (len > 0). -Additionally, if `SQLQueryer` or `SQLExecer` are implemented, you have the option to also set either the `QueryerResultHandler` or `ExecerResultHandler` functions. These functions allow you to evaluate the result of a query or exec operation. If you choose not to implement these yourself, the default handlers are used. +Additionally, if `SQLQueryer` or `SQLExecer` are implemented, you have the option to also set either the `QueryerResultHandler` or `ExecerResultHandler` functions. These functions allow you to evaluate the result of a query or exec operation. If you choose not to implement these yourself, the default handlers are used. The default `ExecerResultHandler` is successful if the passed exec operation affected one and only one row. The default `QueryerResultHandler` is successful if the passed query operation returned one and only one row. #### SQLPinger + Use the `SQLPinger` interface if your health check is only concerned with your application's database connectivity. All you need to do is set the `Pinger` value in your `SQLConfig`. ```golang @@ -80,11 +82,13 @@ Use the `SQLPinger` interface if your health check is only concerned with your a ``` #### SQLQueryer -Use the `SQLQueryer` interface if your health check requires you to read rows from your database. You can optionally supply a query result handler function. If you don't supply one, the default function will be used. The function signature for the handler is: + +Use the `SQLQueryer` interface if your health check requires you to read rows from your database. You can optionally supply a query result handler function. If you don't supply one, the default function will be used. The function signature for the handler is: ```golang type SQLQueryerResultHandler func(rows *sql.Rows) (bool, error) ``` + The default query handler returns true if there was exactly one row in the resultset: ```golang @@ -146,7 +150,8 @@ Sample `SQLQueryer` implementation: ``` #### SQLExecer -Use the `SQLExecer` interface if your health check requires you to update or insert to your database. You can optionally supply an exec result handler function. If you don't supply one, the default function will be used. The function signature for the handler is: + +Use the `SQLExecer` interface if your health check requires you to update or insert to your database. You can optionally supply an exec result handler function. If you don't supply one, the default function will be used. The function signature for the handler is: ```golang type SQLExecerResultHandler func(result sql.Result) (bool, error) diff --git a/checkers/disk/disk_usage.go b/checkers/disk/disk_usage.go index 4e6afab..8412104 100644 --- a/checkers/disk/disk_usage.go +++ b/checkers/disk/disk_usage.go @@ -1,6 +1,7 @@ package diskchk import ( + "context" "fmt" "github.com/shirou/gopsutil/disk" @@ -10,9 +11,12 @@ import ( // // "Path" is _required_; path to check directory/drive (ex. /home/user) // "WarningThreshold" is _required_; set percent (more than 0 and less 100) of free space at specified path, -// which triggers warning. +// +// which triggers warning. +// // "CriticalThreshold" is _required_; set percent (more than 0 and less 100) of free space at specified path, -// which triggers critical. +// +// which triggers critical. type DiskUsageConfig struct { Path string WarningThreshold float64 @@ -40,7 +44,7 @@ func NewDiskUsage(cfg *DiskUsageConfig) (*DiskUsage, error) { // Status is used for performing a diskusage check against a dependency; it satisfies // the "ICheckable" interface. -func (d *DiskUsage) Status() (interface{}, error) { +func (d *DiskUsage) Status(ctx context.Context) (interface{}, error) { stats, err := disk.Usage(d.Config.Path) if err != nil { diff --git a/checkers/disk/disk_usage_test.go b/checkers/disk/disk_usage_test.go index e259a3c..e207378 100644 --- a/checkers/disk/disk_usage_test.go +++ b/checkers/disk/disk_usage_test.go @@ -1,6 +1,7 @@ package diskchk import ( + "context" "os" "testing" @@ -98,7 +99,7 @@ func TestDiskUsageStatus(t *testing.T) { t.Fatal(err) } - _, err = du.Status() + _, err = du.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Error getting disk usage")) }) @@ -115,7 +116,7 @@ func TestDiskUsageStatus(t *testing.T) { t.Fatal(err) } - _, err = du.Status() + _, err = du.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Critical: disk usage too high")) }) @@ -131,7 +132,7 @@ func TestDiskUsageStatus(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = du.Status() + _, err = du.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Warning: disk usage too high")) }) @@ -147,7 +148,7 @@ func TestDiskUsageStatus(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = du.Status() + _, err = du.Status(context.TODO()) Expect(err).To(BeNil()) }) } diff --git a/checkers/http.go b/checkers/http.go index 43298a9..61c939a 100644 --- a/checkers/http.go +++ b/checkers/http.go @@ -2,6 +2,7 @@ package checkers import ( "bytes" + "context" "encoding/json" "errors" "fmt" @@ -63,7 +64,7 @@ func NewHTTP(cfg *HTTPConfig) (*HTTP, error) { // Status is used for performing an HTTP check against a dependency; it satisfies // the "ICheckable" interface. -func (h *HTTP) Status() (interface{}, error) { +func (h *HTTP) Status(ctx context.Context) (interface{}, error) { resp, err := h.do() if err != nil { return nil, err diff --git a/checkers/http_test.go b/checkers/http_test.go index ff5b2a4..a132c6a 100644 --- a/checkers/http_test.go +++ b/checkers/http_test.go @@ -1,6 +1,7 @@ package checkers import ( + "context" "math" "net/http" "net/http/httptest" @@ -9,6 +10,7 @@ import ( "time" "fmt" + . "github.com/onsi/gomega" ) @@ -164,7 +166,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) Expect(data).To(BeNil()) }) @@ -179,7 +181,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("unsupported protocol")) Expect(data).To(BeNil()) @@ -201,7 +203,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("does not match expected status code")) Expect(data).To(BeNil()) @@ -225,7 +227,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("does not contain expected content")) Expect(data).To(BeNil()) @@ -249,7 +251,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) Expect(data).To(BeNil()) }) @@ -277,7 +279,7 @@ func TestHTTPStatus(t *testing.T) { checker, err := NewHTTP(cfg) Expect(err).ToNot(HaveOccurred()) - data, err := checker.Status() + data, err := checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unable to read response body to perform content expectancy check")) diff --git a/checkers/memcache/memcached.go b/checkers/memcache/memcached.go index 7a2a1df..4d14e0a 100644 --- a/checkers/memcache/memcached.go +++ b/checkers/memcache/memcached.go @@ -2,6 +2,7 @@ package memcachechk import ( "bytes" + "context" "fmt" "net" "net/url" @@ -83,7 +84,7 @@ func NewMemcached(cfg *MemcachedConfig) (*Memcached, error) { }, nil } -func (mc *Memcached) Status() (interface{}, error) { +func (mc *Memcached) Status(ctx context.Context) (interface{}, error) { if mc.Config.Ping { if _, err := net.Dial("tcp", mc.Config.Url); err != nil { diff --git a/checkers/memcache/memcached_test.go b/checkers/memcache/memcached_test.go index f01464e..6df97a4 100644 --- a/checkers/memcache/memcached_test.go +++ b/checkers/memcache/memcached_test.go @@ -1,6 +1,7 @@ package memcachechk import ( + "context" "fmt" "math/rand" "strconv" @@ -140,10 +141,10 @@ func TestMemcachedStatus(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err.Error()).To(ContainSubstring("Ping failed")) }) @@ -162,7 +163,7 @@ func TestMemcachedStatus(t *testing.T) { // Mark server is stoppped server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unable to complete set")) }) @@ -180,7 +181,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) val, err := checker.wrapper.GetClient().Get(cfg.Set.Key) @@ -200,7 +201,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) val, err := checker.wrapper.GetClient().Get(cfg.Set.Key) @@ -221,7 +222,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) val, err := checker.wrapper.GetClient().Get(cfg.Set.Key) @@ -243,7 +244,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("Unable to complete get: '%v' not found", cfg.Get.Key))) @@ -262,7 +263,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) }) @@ -281,7 +282,7 @@ func TestMemcachedStatus(t *testing.T) { // Close the server so the GET fails server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unable to complete get")) }) @@ -304,7 +305,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("does not match expected value")) }) @@ -325,7 +326,7 @@ func TestMemcachedStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) }) }) diff --git a/checkers/reachable.go b/checkers/reachable.go index 30113fa..e158016 100644 --- a/checkers/reachable.go +++ b/checkers/reachable.go @@ -1,6 +1,7 @@ package checkers import ( + "context" "net" "net/url" "time" @@ -87,7 +88,7 @@ func NewReachableChecker(cfg *ReachableConfig) (*ReachableChecker, error) { } // Status checks if the endpoint is reachable -func (r *ReachableChecker) Status() (interface{}, error) { +func (r *ReachableChecker) Status(ctx context.Context) (interface{}, error) { // We must provide a port so when a port is not set in the URL provided use // the default port (80) port := r.url.Port() diff --git a/checkers/reachable_test.go b/checkers/reachable_test.go index 6de64c3..0adbe93 100644 --- a/checkers/reachable_test.go +++ b/checkers/reachable_test.go @@ -1,16 +1,18 @@ package checkers_test import ( + "context" "errors" "net" "net/url" "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/InVisionApp/go-health/v2/checkers" "github.com/InVisionApp/go-health/v2/fakes" "github.com/InVisionApp/go-health/v2/fakes/netfakes" - "github.com/stretchr/testify/assert" ) func TestReachableSuccessUsingDefaults(t *testing.T) { @@ -34,7 +36,7 @@ func TestReachableSuccessUsingDefaults(t *testing.T) { assert.NoError(err) assert.NotNil(c) - _, err = c.Status() + _, err = c.Status(context.TODO()) assert.NoError(err) assert.Equal(0, dd.IncrCallCount()) } @@ -64,7 +66,7 @@ func TestReachableSuccess(t *testing.T) { assert.NoError(err) assert.NotNil(c) - _, err = c.Status() + _, err = c.Status(context.TODO()) assert.NoError(err) assert.Equal(0, dd.IncrCallCount()) } @@ -82,7 +84,7 @@ func TestReachableError(t *testing.T) { assert.NoError(err) assert.NotNil(c) - _, err = c.Status() + _, err = c.Status(context.TODO()) assert.Error(err) } @@ -102,7 +104,7 @@ func TestReachableConnError(t *testing.T) { assert.NoError(err) assert.NotNil(c) - _, err = c.Status() + _, err = c.Status(context.TODO()) assert.EqualError(err, expectedErr.Error()) } @@ -125,7 +127,7 @@ func TestReachableErrorWithDatadog(t *testing.T) { assert.NoError(err) assert.NotNil(c) - _, err = c.Status() + _, err = c.Status(context.TODO()) assert.Error(err) assert.Equal(1, dd.IncrCallCount()) name, tags, num := dd.IncrArgsForCall(0) diff --git a/checkers/redis/redis.go b/checkers/redis/redis.go index ac8dfbe..6b08ea3 100644 --- a/checkers/redis/redis.go +++ b/checkers/redis/redis.go @@ -1,6 +1,7 @@ package redischk import ( + "context" "crypto/tls" "fmt" "time" @@ -108,7 +109,7 @@ func NewRedis(cfg *RedisConfig) (*Redis, error) { // Status is used for performing a redis check against a dependency; it satisfies // the "ICheckable" interface. -func (r *Redis) Status() (interface{}, error) { +func (r *Redis) Status(ctx context.Context) (interface{}, error) { if r.Config.Ping { if _, err := r.client.Ping().Result(); err != nil { return nil, fmt.Errorf("Ping failed: %v", err) diff --git a/checkers/redis/redis_test.go b/checkers/redis/redis_test.go index 8e16e53..7010e3d 100644 --- a/checkers/redis/redis_test.go +++ b/checkers/redis/redis_test.go @@ -1,6 +1,7 @@ package redischk import ( + "context" "fmt" "testing" @@ -150,7 +151,7 @@ func TestRedisStatus(t *testing.T) { Expect(err).ToNot(HaveOccurred()) - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Ping failed")) }) @@ -170,7 +171,7 @@ func TestRedisStatus(t *testing.T) { // Stop the server, so ping check fails server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unable to complete set")) }) @@ -188,7 +189,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) val, err := server.Get(cfg.Set.Key) @@ -208,7 +209,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) val, err := server.Get(cfg.Set.Key) @@ -230,7 +231,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("Unable to complete get: '%v' not found", cfg.Get.Key))) }) @@ -248,7 +249,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) }) @@ -267,7 +268,7 @@ func TestRedisStatus(t *testing.T) { // Close the server so the GET fails server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unable to complete get")) }) @@ -290,7 +291,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("does not match expected value")) }) @@ -311,7 +312,7 @@ func TestRedisStatus(t *testing.T) { } defer server.Close() - _, err = checker.Status() + _, err = checker.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) }) }) diff --git a/checkers/sql.go b/checkers/sql.go index 9b31b3d..51cad4e 100644 --- a/checkers/sql.go +++ b/checkers/sql.go @@ -36,7 +36,6 @@ type SQLExecerResultHandler func(result sql.Result) (bool, error) // SQLConfig is used for configuring a database check. // One of the Pinger, Queryer, or Execer fields is required. // -// // If Execer is set, it will take precedence over Queryer and Pinger, // Execer implements the SQLExecer interface in this package. // The sql.DB and sql.TX structs both implement this interface. @@ -44,7 +43,6 @@ type SQLExecerResultHandler func(result sql.Result) (bool, error) // Note that if the Execer is set, then the ExecerResultHandler // and Query values MUST also be set // -// // If Queryer is set, it will take precedence over Pinger. // SQLQueryer implements the SQLQueryer interface in this package. // The sql.DB and sql.TX structs both implement this interface. @@ -52,7 +50,6 @@ type SQLExecerResultHandler func(result sql.Result) (bool, error) // Note that if the Queryer is set, then the QueryerResultHandler // and Query values MUST also be set // -// // Pinger implements the SQLPinger interface in this package. // The sql.DB struct implements this interface. type SQLConfig struct { @@ -140,7 +137,7 @@ func validateSQLConfig(cfg *SQLConfig) error { // Status is used for performing a database ping against a dependency; it satisfies // the "ICheckable" interface. -func (s *SQL) Status() (interface{}, error) { +func (s *SQL) Status(ctx context.Context) (interface{}, error) { if err := validateSQLConfig(s.Config); err != nil { return nil, err } diff --git a/checkers/sql_test.go b/checkers/sql_test.go index 22de776..11b6f59 100644 --- a/checkers/sql_test.go +++ b/checkers/sql_test.go @@ -157,7 +157,7 @@ func TestSQLStatus(t *testing.T) { Expect(err).To(BeNil()) Expect(s).ToNot(BeNil()) - nothing, err := s.Status() + nothing, err := s.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) // status check returns no artifacts @@ -172,7 +172,7 @@ func TestSQLStatus(t *testing.T) { Expect(err).To(BeNil()) Expect(s).ToNot(BeNil()) - _, err = s.Status() + _, err = s.Status(context.TODO()) Expect(err).ToNot(HaveOccurred()) }) @@ -184,13 +184,13 @@ func TestSQLStatus(t *testing.T) { Expect(err).To(BeNil()) Expect(s).ToNot(BeNil()) - _, err = s.Status() + _, err = s.Status(context.TODO()) Expect(err).To(HaveOccurred()) }) t.Run("bad config", func(t *testing.T) { s := &SQL{} - _, err := s.Status() + _, err := s.Status(context.TODO()) Expect(err).To(HaveOccurred()) }) } @@ -210,7 +210,7 @@ func TestDefaultExecHandler(t *testing.T) { }) Expect(err).To(BeNil()) - _, err = s.Status() + _, err = s.Status(context.TODO()) Expect(err).To(BeNil()) }) @@ -301,7 +301,7 @@ func TestDefaultQueryHandler(t *testing.T) { }) Expect(err).To(BeNil()) - _, err = s.Status() + _, err = s.Status(context.TODO()) Expect(err).To(BeNil()) }) diff --git a/examples/custom-checker-server/custom-checker-server.go b/examples/custom-checker-server/custom-checker-server.go index 93641dc..53ddb70 100644 --- a/examples/custom-checker-server/custom-checker-server.go +++ b/examples/custom-checker-server/custom-checker-server.go @@ -6,6 +6,8 @@ import ( "net/http" "time" + "golang.org/x/net/context" + "github.com/InVisionApp/go-health/v2" "github.com/InVisionApp/go-health/v2/handlers" ) @@ -42,7 +44,7 @@ func main() { } // Satisfy the go-health.ICheckable interface -func (c *customCheck) Status() (interface{}, error) { +func (c *customCheck) Status(ctx context.Context) (interface{}, error) { // perform some sort of check if false { return nil, fmt.Errorf("Something major just broke") diff --git a/fakes/icheckable.go b/fakes/icheckable.go index 49e848e..6dddd07 100644 --- a/fakes/icheckable.go +++ b/fakes/icheckable.go @@ -1,16 +1,20 @@ // Code generated by counterfeiter. DO NOT EDIT. -// (with minor, manual edits) package fakes import ( + "context" "sync" + + "github.com/InVisionApp/go-health" ) type FakeICheckable struct { - StatusStub func() (interface{}, error) + StatusStub func(ctx context.Context) (interface{}, error) statusMutex sync.RWMutex - statusArgsForCall []struct{} - statusReturns struct { + statusArgsForCall []struct { + ctx context.Context + } + statusReturns struct { result1 interface{} result2 error } @@ -22,14 +26,16 @@ type FakeICheckable struct { invocationsMutex sync.RWMutex } -func (fake *FakeICheckable) Status() (interface{}, error) { +func (fake *FakeICheckable) Status(ctx context.Context) (interface{}, error) { fake.statusMutex.Lock() ret, specificReturn := fake.statusReturnsOnCall[len(fake.statusArgsForCall)] - fake.statusArgsForCall = append(fake.statusArgsForCall, struct{}{}) - fake.recordInvocation("Status", []interface{}{}) + fake.statusArgsForCall = append(fake.statusArgsForCall, struct { + ctx context.Context + }{ctx}) + fake.recordInvocation("Status", []interface{}{ctx}) fake.statusMutex.Unlock() if fake.StatusStub != nil { - return fake.StatusStub() + return fake.StatusStub(ctx) } if specificReturn { return ret.result1, ret.result2 @@ -43,6 +49,12 @@ func (fake *FakeICheckable) StatusCallCount() int { return len(fake.statusArgsForCall) } +func (fake *FakeICheckable) StatusArgsForCall(i int) context.Context { + fake.statusMutex.RLock() + defer fake.statusMutex.RUnlock() + return fake.statusArgsForCall[i].ctx +} + func (fake *FakeICheckable) StatusReturns(result1 interface{}, result2 error) { fake.StatusStub = nil fake.statusReturns = struct { @@ -88,3 +100,5 @@ func (fake *FakeICheckable) recordInvocation(key string, args []interface{}) { } fake.invocations[key] = append(fake.invocations[key], args) } + +var _ health.ICheckable = new(FakeICheckable) diff --git a/fakes/isqlexecer.go b/fakes/isqlexecer.go index 1a1cecf..f912fe8 100644 --- a/fakes/isqlexecer.go +++ b/fakes/isqlexecer.go @@ -6,7 +6,7 @@ import ( "database/sql" "sync" - "github.com/InVisionApp/go-health/v2/checkers" + "github.com/InVisionApp/go-health/checkers" ) type FakeSQLExecer struct { diff --git a/fakes/isqlpinger.go b/fakes/isqlpinger.go index e4aab8a..b4858b4 100644 --- a/fakes/isqlpinger.go +++ b/fakes/isqlpinger.go @@ -5,7 +5,7 @@ import ( "context" "sync" - "github.com/InVisionApp/go-health/v2/checkers" + "github.com/InVisionApp/go-health/checkers" ) type FakeSQLPinger struct { diff --git a/fakes/isqlqueryer.go b/fakes/isqlqueryer.go index 9106dde..34980be 100644 --- a/fakes/isqlqueryer.go +++ b/fakes/isqlqueryer.go @@ -6,7 +6,7 @@ import ( "database/sql" "sync" - "github.com/InVisionApp/go-health/v2/checkers" + "github.com/InVisionApp/go-health/checkers" ) type FakeSQLQueryer struct { diff --git a/go.mod b/go.mod index d721dc8..32dae65 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect github.com/zaffka/mongodb-boltdb-mock v0.0.0-20221014194232-b4bb03fbe3a0 go.mongodb.org/mongo-driver v1.13.1 + golang.org/x/net v0.0.0-20220722155237-a158d28d115b gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/health.go b/health.go index f542236..695ccd4 100644 --- a/health.go +++ b/health.go @@ -6,11 +6,12 @@ package health import ( + "context" "errors" "sync" "time" - "github.com/InVisionApp/go-logger" + log "github.com/InVisionApp/go-logger" ) //go:generate counterfeiter -o ./fakes/icheckable.go . ICheckable @@ -48,7 +49,7 @@ type ICheckable interface { // Status allows you to return additional data as an "interface{}" and "error" // to signify that the check has failed. If "interface{}" is non-nil, it will // be exposed under "State.Details" for that particular check. - Status() (interface{}, error) + Status(ctx context.Context) (interface{}, error) } // IStatusListener is an interface that handles health check failures and @@ -249,7 +250,7 @@ func (h *Health) startRunner(cfg *Config, ticker *time.Ticker, stop <-chan struc // function to execute and collect check data checkFunc := func() { - data, err := cfg.Checker.Status() + data, err := cfg.Checker.Status(context.TODO()) stateEntry := &State{ Name: cfg.Name,