From 276c9540b48bc9ec2a8f34553d96a4ca0ce2681a Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Fri, 23 Jan 2015 13:40:38 -0800 Subject: [PATCH] etcdserver: support raft.status --- etcdserver/server.go | 5 +++++ raft/status.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/etcdserver/server.go b/etcdserver/server.go index 4d75f07ff..264b28b44 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -16,6 +16,7 @@ package etcdserver import ( "encoding/json" + "expvar" "fmt" "io/ioutil" "log" @@ -33,6 +34,7 @@ import ( "github.com/coreos/etcd/etcdserver/stats" "github.com/coreos/etcd/pkg/fileutil" "github.com/coreos/etcd/pkg/idutil" + "github.com/coreos/etcd/pkg/metrics" "github.com/coreos/etcd/pkg/pbutil" "github.com/coreos/etcd/pkg/timeutil" "github.com/coreos/etcd/pkg/types" @@ -266,6 +268,7 @@ func (s *EtcdServer) Start() { s.start() go s.publish(defaultPublishRetryInterval) go s.purgeFile() + metrics.Publish("raft.status", expvar.Func(s.raftStatus)) } // start prepares and starts server in a new goroutine. It is no longer safe to @@ -513,6 +516,8 @@ func (s *EtcdServer) LeaderStats() []byte { func (s *EtcdServer) StoreStats() []byte { return s.store.JsonStats() } +func (s *EtcdServer) raftStatus() interface{} { return s.r.Status() } + func (s *EtcdServer) AddMember(ctx context.Context, memb Member) error { // TODO: move Member to protobuf type b, err := json.Marshal(memb) diff --git a/raft/status.go b/raft/status.go index 112e8a98e..d7768800b 100644 --- a/raft/status.go +++ b/raft/status.go @@ -15,6 +15,9 @@ package raft import ( + "fmt" + "log" + pb "github.com/coreos/etcd/raft/raftpb" ) @@ -45,3 +48,29 @@ func getStatus(r *raft) Status { return s } + +// TODO: try to simplify this by introducing ID type into raft +func (s Status) MarshalJSON() ([]byte, error) { + j := fmt.Sprintf(`{"id":"%x","term":%d,"vote":"%x","commit":%d,"lead":"%x","raftState":"%s","progress":{`, + s.ID, s.Term, s.Vote, s.Commit, s.Lead, s.RaftState) + + if len(s.Progress) == 0 { + j += "}}" + } else { + for k, v := range s.Progress { + subj := fmt.Sprintf(`"%x":{"match":%d,"next":%d},`, k, v.Match, v.Next) + j += subj + } + // remove the trailing "," + j = j[:len(j)-1] + "}}" + } + return []byte(j), nil +} + +func (s Status) String() string { + b, err := s.MarshalJSON() + if err != nil { + log.Panicf("unexpected error: %v", err) + } + return string(b) +}