Browse Source

Merge pull request #2120 from bdarnell/formatter

raft: Add support for custom formatters in DescribeMessage/DescribeEntry
Xiang Li 11 years ago
parent
commit
4409e88358
2 changed files with 61 additions and 4 deletions
  1. 14 4
      raft/util.go
  2. 47 0
      raft/util_test.go

+ 14 - 4
raft/util.go

@@ -54,9 +54,13 @@ func IsResponseMsg(m pb.Message) bool {
 	return m.Type == pb.MsgAppResp || m.Type == pb.MsgVoteResp || m.Type == pb.MsgHeartbeatResp
 	return m.Type == pb.MsgAppResp || m.Type == pb.MsgVoteResp || m.Type == pb.MsgHeartbeatResp
 }
 }
 
 
+// EntryFormatter can be implemented by the application to provide human-readable formatting
+// of entry data. Nil is a valid EntryFormatter and will use a default format.
+type EntryFormatter func([]byte) string
+
 // DescribeMessage returns a concise human-readable description of a
 // DescribeMessage returns a concise human-readable description of a
 // Message for debugging.
 // Message for debugging.
-func DescribeMessage(m pb.Message) string {
+func DescribeMessage(m pb.Message, f EntryFormatter) string {
 	var buf bytes.Buffer
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, "%d->%d %s Term:%d Log:%d/%d", m.From, m.To, m.Type, m.Term, m.LogTerm, m.Index)
 	fmt.Fprintf(&buf, "%d->%d %s Term:%d Log:%d/%d", m.From, m.To, m.Type, m.Term, m.LogTerm, m.Index)
 	if m.Reject {
 	if m.Reject {
@@ -68,7 +72,7 @@ func DescribeMessage(m pb.Message) string {
 	if len(m.Entries) > 0 {
 	if len(m.Entries) > 0 {
 		fmt.Fprintf(&buf, " Entries:[")
 		fmt.Fprintf(&buf, " Entries:[")
 		for _, e := range m.Entries {
 		for _, e := range m.Entries {
-			buf.WriteString(DescribeEntry(e))
+			buf.WriteString(DescribeEntry(e, f))
 		}
 		}
 		fmt.Fprintf(&buf, "]")
 		fmt.Fprintf(&buf, "]")
 	}
 	}
@@ -80,6 +84,12 @@ func DescribeMessage(m pb.Message) string {
 
 
 // DescribeEntry returns a concise human-readable description of an
 // DescribeEntry returns a concise human-readable description of an
 // Entry for debugging.
 // Entry for debugging.
-func DescribeEntry(e pb.Entry) string {
-	return fmt.Sprintf("%d/%d %s %q", e.Term, e.Index, e.Type, string(e.Data))
+func DescribeEntry(e pb.Entry, f EntryFormatter) string {
+	var formatted string
+	if f == nil {
+		formatted = fmt.Sprintf("%q", e.Data)
+	} else {
+		formatted = f(e.Data)
+	}
+	return fmt.Sprintf("%d/%d %s %s", e.Term, e.Index, e.Type, formatted)
 }
 }

+ 47 - 0
raft/util_test.go

@@ -0,0 +1,47 @@
+/*
+   Copyright 2014 CoreOS, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package raft
+
+import (
+	"strings"
+	"testing"
+
+	pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+var testFormatter EntryFormatter = func(data []byte) string {
+	return strings.ToUpper(string(data))
+}
+
+func TestDescribeEntry(t *testing.T) {
+	entry := pb.Entry{
+		Term:  1,
+		Index: 2,
+		Type:  pb.EntryNormal,
+		Data:  []byte("hello\x00world"),
+	}
+
+	defaultFormatted := DescribeEntry(entry, nil)
+	if defaultFormatted != "1/2 EntryNormal \"hello\\x00world\"" {
+		t.Errorf("unexpected default output: %s", defaultFormatted)
+	}
+
+	customFormatted := DescribeEntry(entry, testFormatter)
+	if customFormatted != "1/2 EntryNormal HELLO\x00WORLD" {
+		t.Errorf("unexpected custom output: %s", customFormatted)
+	}
+}