Skip to content

Commit

Permalink
Add custom String() formatter to Membership
Browse files Browse the repository at this point in the history
Close hashicorp#167: Make the stats into a real structure
  • Loading branch information
ongardie committed Oct 31, 2016
1 parent afc0350 commit 6b320ce
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
2 changes: 1 addition & 1 deletion api.go
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ func (s *Stats) Strings() []struct{ K, V string } {
{"fsm_pending", toString(uint64(s.FSMPending))},
{"last_snapshot_index", toString(uint64(s.LastSnapshotIndex))},
{"last_snapshot_term", toString(uint64(s.LastSnapshotTerm))},
{"latest_membership", fmt.Sprintf("%+v", s.LatestMembership.Servers)},
{"latest_membership", fmt.Sprintf("%v", s.LatestMembership)},
{"latest_membership_index", toString(uint64(s.LatestMembershipIndex))},
{"last_contact", lastContact},
{"num_peers", toString(uint64(s.NumPeers))},
Expand Down
37 changes: 35 additions & 2 deletions api_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package raft

import "testing"
import (
"fmt"
"testing"
)

func TestAPI_Stats(t *testing.T) {
c := MakeCluster(1, t, nil)
defer c.Close()
future := c.rafts[0].Stats()
if err := future.Error(); err != nil {
c.FailNowf("Stats() returned err %v", err)
Expand All @@ -12,5 +16,34 @@ func TestAPI_Stats(t *testing.T) {
if s.LastLogTerm != 1 {
c.FailNowf("stats.LastLogTerm expected 1, got %v", s.LastLogTerm)
}
c.Close()
}

func TestAPI_Stats_membershipFormatting(t *testing.T) {
c := MakeCluster(1, t, nil)
defer c.Close()
c.GetInState(Leader)
addFuture := c.rafts[0].AddNonvoter("S2", "s2-addr", 0, 0)
err := addFuture.Error()
if err != nil {
c.FailNowf("AddNonvoter() returned err %v", err)
}

statsFuture := c.rafts[0].Stats()
err = statsFuture.Error()
if err != nil {
c.FailNowf("Stats() returned err %v", err)
}
s := statsFuture.Stats()
membership := "not found"
for _, kv := range s.Strings() {
if kv.K == "latest_membership" {
membership = kv.V
}
}
exp := fmt.Sprintf("[%v at %v (Voter), S2 at s2-addr (Nonvoter)]",
c.rafts[0].server.localID, c.rafts[0].server.localAddr)
if membership != exp {
c.Failf("membership not stringified correctly. Expected: '%s', got: '%s'",
exp, membership)
}
}
14 changes: 13 additions & 1 deletion membership.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package raft

import "fmt"
import (
"fmt"
"strings"
)

// Membership changes follow the single-server algorithm described in Diego
// Ongaro's PhD dissertation. The Membership struct defines a cluster membership
Expand Down Expand Up @@ -85,6 +88,15 @@ type Membership struct {
Servers []Server
}

func (m Membership) String() string {
vec := make([]string, 0, len(m.Servers))
for _, server := range m.Servers {
vec = append(vec, fmt.Sprintf("%s at %s (%s)",
server.ID, server.Address, server.Suffrage))
}
return fmt.Sprintf("[%s]", strings.Join(vec, ", "))
}

// Clone makes a deep copy of a Membership.
func (m *Membership) Clone() (copy Membership) {
copy.Servers = append(copy.Servers, m.Servers...)
Expand Down

0 comments on commit 6b320ce

Please sign in to comment.