Merge pull request #2120 from bdarnell/formatter

raft: Add support for custom formatters in DescribeMessage/DescribeEntry
release-2.0
Xiang Li 2015-01-21 16:32:59 -08:00
commit 4409e88358
2 changed files with 61 additions and 4 deletions

View File

@ -54,9 +54,13 @@ func IsResponseMsg(m pb.Message) bool {
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
// Message for debugging.
func DescribeMessage(m pb.Message) string {
func DescribeMessage(m pb.Message, f EntryFormatter) string {
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)
if m.Reject {
@ -68,7 +72,7 @@ func DescribeMessage(m pb.Message) string {
if len(m.Entries) > 0 {
fmt.Fprintf(&buf, " Entries:[")
for _, e := range m.Entries {
buf.WriteString(DescribeEntry(e))
buf.WriteString(DescribeEntry(e, f))
}
fmt.Fprintf(&buf, "]")
}
@ -80,6 +84,12 @@ func DescribeMessage(m pb.Message) string {
// DescribeEntry returns a concise human-readable description of an
// 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
raft/util_test.go Normal file
View File

@ -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)
}
}