Browse Source

Merge pull request #2140 from xiang90/raft_stats

etcdserver: support raft.status
Xiang Li 11 years ago
parent
commit
915c22292f
2 changed files with 34 additions and 0 deletions
  1. 5 0
      etcdserver/server.go
  2. 29 0
      raft/status.go

+ 5 - 0
etcdserver/server.go

@@ -16,6 +16,7 @@ package etcdserver
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"expvar"
 	"fmt"
 	"fmt"
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
@@ -33,6 +34,7 @@ import (
 	"github.com/coreos/etcd/etcdserver/stats"
 	"github.com/coreos/etcd/etcdserver/stats"
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/idutil"
 	"github.com/coreos/etcd/pkg/idutil"
+	"github.com/coreos/etcd/pkg/metrics"
 	"github.com/coreos/etcd/pkg/pbutil"
 	"github.com/coreos/etcd/pkg/pbutil"
 	"github.com/coreos/etcd/pkg/timeutil"
 	"github.com/coreos/etcd/pkg/timeutil"
 	"github.com/coreos/etcd/pkg/types"
 	"github.com/coreos/etcd/pkg/types"
@@ -266,6 +268,7 @@ func (s *EtcdServer) Start() {
 	s.start()
 	s.start()
 	go s.publish(defaultPublishRetryInterval)
 	go s.publish(defaultPublishRetryInterval)
 	go s.purgeFile()
 	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
 // 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) 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 {
 func (s *EtcdServer) AddMember(ctx context.Context, memb Member) error {
 	// TODO: move Member to protobuf type
 	// TODO: move Member to protobuf type
 	b, err := json.Marshal(memb)
 	b, err := json.Marshal(memb)

+ 29 - 0
raft/status.go

@@ -15,6 +15,9 @@
 package raft
 package raft
 
 
 import (
 import (
+	"fmt"
+	"log"
+
 	pb "github.com/coreos/etcd/raft/raftpb"
 	pb "github.com/coreos/etcd/raft/raftpb"
 )
 )
 
 
@@ -45,3 +48,29 @@ func getStatus(r *raft) Status {
 
 
 	return s
 	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)
+}