From 9c3166b5a63344e0eda21410ecf181faa09a2ee5 Mon Sep 17 00:00:00 2001 From: Vishal Lal Date: Tue, 18 Oct 2016 17:02:55 -0700 Subject: [PATCH] Initial checkin for expansion --- endpoints.go | 8 +++----- middlewares.go | 19 +++++++++++++++++++ service.go | 31 +++++++++++++++++++++++++++++-- test/container.py | 12 +++++++++--- transport.go | 2 +- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/endpoints.go b/endpoints.go index 1be0d36c..448e5838 100644 --- a/endpoints.go +++ b/endpoints.go @@ -5,8 +5,6 @@ package catalogue // transport. import ( - "time" - "github.com/go-kit/kit/endpoint" "golang.org/x/net/context" ) @@ -70,7 +68,8 @@ func MakeTagsEndpoint(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 } } @@ -118,6 +117,5 @@ type healthRequest struct { } type healthResponse struct { - Status string `json:"status"` - Time string `json:"time"` + Health []Health `json:"health"` } diff --git a/middlewares.go b/middlewares.go index 8c127a8a..f2b8ffd6 100644 --- a/middlewares.go +++ b/middlewares.go @@ -80,6 +80,17 @@ func (mw loggingMiddleware) Tags() (tags []string, err error) { return mw.next.Tags() } +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 @@ -130,3 +141,11 @@ func (s *instrumentingService) Tags() ([]string, error) { return s.Service.Tags() } + +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/service.go b/service.go index d1c8723a..4e0b25a0 100644 --- a/service.go +++ b/service.go @@ -6,6 +6,7 @@ package catalogue import ( "errors" "strings" + "time" "github.com/go-kit/kit/log" "github.com/jmoiron/sqlx" @@ -18,6 +19,7 @@ type Service interface { Count(tags []string) (int, error) // GET /catalogue/size Get(id string) (Sock, error) // GET /catalogue/{id} Tags() ([]string, error) // GET /tags + Health() []Health // GET /health } // Sock describes the thing on offer in the catalogue. @@ -34,6 +36,13 @@ type Sock struct { TagString string `json:"-" db:"tag_name"` } +// Health describes the health of a service +type Health struct { + Service string `json:"service"` + Status string `json:"status"` + Time string `json:"time"` +} + // ErrNotFound is returned when there is no sock for a given ID. var ErrNotFound = errors.New("not found") @@ -46,13 +55,13 @@ var baseQuery = "SELECT sock.sock_id AS id, sock.name, sock.description, sock.pr // with connection to an SQL database. func NewCatalogueService(db *sqlx.DB, logger log.Logger) Service { return &catalogueService{ - db: db, + db: db, logger: logger, } } type catalogueService struct { - db *sqlx.DB + db *sqlx.DB logger log.Logger } @@ -148,6 +157,24 @@ func (s *catalogueService) Get(id string) (Sock, error) { return sock, nil } +func (s *catalogueService) Health() []Health { + var health []Health + dbstatus := "OK" + + err := s.db.Ping() + if err != nil { + dbstatus = "err" + } + + app := Health{"catalogue", "OK", time.Now().String()} + db := Health{"catalogue-db", dbstatus, time.Now().String()} + + health = append(health, app) + health = append(health, db) + + return health +} + func (s *catalogueService) Tags() ([]string, error) { var tags []string query := "SELECT name FROM tag;" diff --git a/test/container.py b/test/container.py index 79eadf2e..cbf31826 100644 --- a/test/container.py +++ b/test/container.py @@ -17,13 +17,19 @@ def __init__(self, methodName='runTest'): self.ip = "" def setUp(self): - Docker().start_container(container_name=self.mysql_container_name, image="mysql", host=self.mysql_container_name, env=[("MYSQL_ROOT_PASSWORD", "abc123"), ("MYSQL_DATABASE", "catalogue")]) + Docker().start_container(container_name=self.mysql_container_name, + image="weaveworksdemos/catalogue-db:" + self.TAG, + host=self.mysql_container_name, + env=[("MYSQL_ROOT_PASSWORD", ""), + ("MYSQL_ALLOW_EMPTY_PASSWORD", True), + ("MYSQL_DATABASE", "socksdb")] + ) # todo: a better way to ensure mysql is up - sleep(15) + sleep(30) command = ['docker', 'run', '-d', '--name', CatalogueContainerTest.container_name, - '--link', "{}:mysql".format(self.mysql_container_name), + '--link', "{}:catalogue-db".format(self.mysql_container_name), '-h', CatalogueContainerTest.container_name, 'weaveworksdemos/catalogue:' + self.TAG] Docker().execute(command) diff --git a/transport.go b/transport.go index 386b6d01..f72ce81d 100644 --- a/transport.go +++ b/transport.go @@ -28,7 +28,7 @@ func MakeHTTPHandler(ctx context.Context, e Endpoints, imagePath string, logger // GET /catalogue/size Count // GET /catalogue/{id} Get // GET /tags Tags - // GET /health Health Check + // GET /health Health Check r.Methods("GET").Path("/catalogue").Handler(httptransport.NewServer( ctx,