Skip to content

Commit

Permalink
api/etcdhttp: serve error information in '/health'
Browse files Browse the repository at this point in the history
Signed-off-by: Gyu-Ho Lee <[email protected]>
  • Loading branch information
gyuho committed Jul 26, 2017
1 parent ee1c340 commit d59fe03
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
2 changes: 1 addition & 1 deletion e2e/ctl_v3_alarm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func alarmTest(cx ctlCtx) {
}

// '/health' handler should return 'false'
if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health": "false"}`}); err != nil {
if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health": "false", "errors": ["NOSPACE"]}`}); err != nil {
cx.t.Fatalf("failed get with curl (%v)", err)
}

Expand Down
35 changes: 29 additions & 6 deletions etcdserver/api/etcdhttp/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"time"

"github.com/coreos/etcd/etcdserver"
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
"github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/raft"

Expand Down Expand Up @@ -57,34 +58,56 @@ func newHealthHandler(srv *etcdserver.EtcdServer) http.HandlerFunc {
return
}
h := checkHealth(srv)
d := []byte(fmt.Sprintf(`{"health": "%v"}`, h.Health))
d := h.marshal()
if !h.Health {
http.Error(w, string(d), http.StatusServiceUnavailable)
http.Error(w, d, http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
w.Write(d)
w.Write([]byte(d))
}
}

type health struct {
Health bool `json:"health"`
Health bool `json:"health"`
Errors []string `json:"errors"`
}

func (h health) marshal() string {
s := fmt.Sprintf(`{"health": "%v"`, h.Health)
if len(h.Errors) > 0 {
ss := []string{}
for _, v := range h.Errors {
ss = append(ss, fmt.Sprintf("%q", v))
}
s += fmt.Sprintf(`, "errors": %v`, ss)
}
s += "}"
return s
}

func checkHealth(srv *etcdserver.EtcdServer) health {
h := health{Health: false}
if len(srv.Alarms()) > 0 {
// TODO: provide alarm lists

as := srv.Alarms()
if len(as) > 0 {
for _, v := range as {
h.Errors = append(h.Errors, v.Alarm.String())
}
return h
}

if uint64(srv.Leader()) == raft.None {
h.Errors = append(h.Errors, rpctypes.ErrNoLeader.Error())
return h
}

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
_, err := srv.Do(ctx, etcdserverpb.Request{Method: "QGET"})
cancel()
if err != nil {
h.Errors = append(h.Errors, err.Error())
}

h.Health = err == nil
return h
Expand Down

0 comments on commit d59fe03

Please sign in to comment.