From 12ad34dd8e96bc5e90235602ebcf7a147eeaf06d Mon Sep 17 00:00:00 2001 From: Vishal Lal Date: Wed, 19 Oct 2016 22:22:27 -0700 Subject: [PATCH 1/3] Inital commit for health endpoint expansion. Add 5second timeout for mongo --- .gitignore | 1 + api/endpoints.go | 8 +++----- api/middlewares.go | 20 ++++++++++++++++++++ api/service.go | 26 ++++++++++++++++++++++++++ db/db.go | 6 ++++++ db/db_test.go | 12 ++++++++++++ db/mongodb/mongodb.go | 9 ++++++++- db/mongodb/mongodb_test.go | 9 +++++++++ 8 files changed, 85 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index df66117a..d083607d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin docker/user/bin +vendor diff --git a/api/endpoints.go b/api/endpoints.go index 50545f77..093afd91 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -5,8 +5,6 @@ package api // transport. import ( - "time" - "github.com/go-kit/kit/endpoint" "github.com/microservices-demo/user/db" "github.com/microservices-demo/user/users" @@ -163,7 +161,8 @@ func MakeDeleteEndpoint(s Service) endpoint.Endpoint { // MakeHealthEndpoint returns current health of the given service. func MakeHealthEndpoint(s Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { - return healthResponse{Status: "OK", Time: time.Now().String()}, nil + health := s.Health() + return healthResponse{Health: health}, nil } } @@ -229,8 +228,7 @@ type healthRequest struct { } type healthResponse struct { - Status string `json:"status"` - Time string `json:"time"` + Health []Health `json:"health"` } type EmbedStruct struct { diff --git a/api/middlewares.go b/api/middlewares.go index fb1e8353..ba6eb560 100644 --- a/api/middlewares.go +++ b/api/middlewares.go @@ -148,6 +148,17 @@ func (mw loggingMiddleware) Delete(entity, id string) (err error) { return mw.next.Delete(entity, id) } +func (mw loggingMiddleware) Health() (health []Health) { + defer func(begin time.Time) { + mw.logger.Log( + "method", "Health", + "result", len(health), + "took", time.Since(begin), + ) + }(time.Now()) + return mw.next.Health() +} + type instrumentingService struct { requestCount metrics.Counter requestLatency metrics.Histogram @@ -243,3 +254,12 @@ func (s *instrumentingService) Delete(entity, id string) error { return s.Service.Delete(entity, id) } + +func (s *instrumentingService) Health() []Health { + defer func(begin time.Time) { + s.requestCount.With("method", "health").Add(1) + s.requestLatency.With("method", "health").Observe(time.Since(begin).Seconds()) + }(time.Now()) + + return s.Service.Health() +} diff --git a/api/service.go b/api/service.go index cb0f8305..68a86949 100644 --- a/api/service.go +++ b/api/service.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "time" "github.com/microservices-demo/user/db" "github.com/microservices-demo/user/users" @@ -28,6 +29,7 @@ type Service interface { GetCards(id string) ([]users.Card, error) PostCard(u users.Card, userid string) (string, error) Delete(entity, id string) error + Health() []Health // GET /health } // NewFixedService returns a simple implementation of the Service interface, @@ -37,6 +39,12 @@ func NewFixedService() Service { type fixedService struct{} +type Health struct { + Service string `json:"service"` + Status string `json:"status"` + Time string `json:"time"` +} + func (s *fixedService) Login(username, password string) (users.User, error) { u, err := db.GetUserByName(username) if err != nil { @@ -125,6 +133,24 @@ func (s *fixedService) Delete(entity, id string) error { return db.Delete(entity, id) } +func (s *fixedService) Health() []Health { + var health []Health + dbstatus := "OK" + + err := db.Ping() + if err != nil { + dbstatus = "err" + } + + app := Health{"user", "OK", time.Now().String()} + db := Health{"user-db", dbstatus, time.Now().String()} + + health = append(health, app) + health = append(health, db) + + return health +} + func calculatePassHash(pass, salt string) string { h := sha1.New() io.WriteString(h, salt) diff --git a/db/db.go b/db/db.go index 4226b099..9f4d28b3 100644 --- a/db/db.go +++ b/db/db.go @@ -25,6 +25,7 @@ type Database interface { GetCards() ([]users.Card, error) Delete(string, string) error CreateCard(*users.Card, string) error + Ping() error } var ( @@ -163,3 +164,8 @@ func GetCards() ([]users.Card, error) { func Delete(entity, id string) error { return DefaultDb.Delete(entity, id) } + +//Ping invokes DefaultDB method +func Ping() error { + return DefaultDb.Ping() +} diff --git a/db/db_test.go b/db/db_test.go index d8a5c075..618d0e55 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -93,6 +93,14 @@ func TestGetUserAttributes(t *testing.T) { } } +func TestPing(t *testing.T) { + err := Ping() + if err != ErrFakeError { + t.Error("expected fake db error from ping") + } + +} + type fake struct{} func (f fake) Init() error { @@ -145,3 +153,7 @@ func (f fake) CreateAddress(u *users.Address, id string) error { func (f fake) Delete(entity, id string) error { return ErrFakeError } + +func (f fake) Ping() error { + return ErrFakeError +} diff --git a/db/mongodb/mongodb.go b/db/mongodb/mongodb.go index 6532f92d..74956d2a 100644 --- a/db/mongodb/mongodb.go +++ b/db/mongodb/mongodb.go @@ -6,6 +6,7 @@ import ( "fmt" "net/url" "os" + "time" "github.com/microservices-demo/user/users" @@ -38,7 +39,7 @@ type Mongo struct { func (m *Mongo) Init() error { u := getURL() var err error - m.Session, err = mgo.Dial(u.String()) + m.Session, err = mgo.DialWithTimeout(u.String(), time.Duration(5)*time.Second) if err != nil { return err } @@ -456,3 +457,9 @@ func (m *Mongo) EnsureIndexes() error { c := s.DB("").C("customers") return c.EnsureIndex(i) } + +func (m *Mongo) Ping() error { + s := m.Session.Copy() + defer s.Close() + return s.Ping() +} diff --git a/db/mongodb/mongodb_test.go b/db/mongodb/mongodb_test.go index 50cdc4bf..480ea960 100644 --- a/db/mongodb/mongodb_test.go +++ b/db/mongodb/mongodb_test.go @@ -149,3 +149,12 @@ func TestGetURL(t *testing.T) { t.Error("expected url mismatch") } } + +func TestPing(t *testing.T) { + TestMongo.Session = TestServer.Session() + defer TestMongo.Session.Close() + err := TestMongo.Ping() + if err != nil { + t.Error(err) + } +} From 0b7f73c10531a0f8b0d2bae77e230d9d4360d57f Mon Sep 17 00:00:00 2001 From: Vishal Lal Date: Mon, 31 Oct 2016 19:32:32 -0700 Subject: [PATCH 2/3] Coverage --- db/mongodb/mongodb_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/db/mongodb/mongodb_test.go b/db/mongodb/mongodb_test.go index 480ea960..de036660 100644 --- a/db/mongodb/mongodb_test.go +++ b/db/mongodb/mongodb_test.go @@ -133,8 +133,12 @@ func TestGetUserByName(t *testing.T) { func TestGetUser(t *testing.T) { TestMongo.Session = TestServer.Session() defer TestMongo.Session.Close() - + u, err := TestMongo.GetUser("1") + if err != nil { + t.Error(err) + } } + func TestGetUserAttributes(t *testing.T) { TestMongo.Session = TestServer.Session() defer TestMongo.Session.Close() From a9e45d05947f892a02c3fc5faf7d131a37ec8b03 Mon Sep 17 00:00:00 2001 From: Vishal Lal Date: Mon, 31 Oct 2016 19:38:38 -0700 Subject: [PATCH 3/3] Fix test --- db/mongodb/mongodb_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/mongodb/mongodb_test.go b/db/mongodb/mongodb_test.go index de036660..929b5dfa 100644 --- a/db/mongodb/mongodb_test.go +++ b/db/mongodb/mongodb_test.go @@ -133,7 +133,7 @@ func TestGetUserByName(t *testing.T) { func TestGetUser(t *testing.T) { TestMongo.Session = TestServer.Session() defer TestMongo.Session.Close() - u, err := TestMongo.GetUser("1") + _, err := TestMongo.GetUser("1") if err != nil { t.Error(err) }