raft: Add support for custom formatters in DescribeMessage/DescribeEntry

This commit is contained in:
Ben Darnell 2015-01-21 14:12:58 -05:00
parent 88704c70e7
commit e73d442e32
2 changed files with 73 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 (f EntryFormatter) DescribeMessage(m pb.Message) 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(f.DescribeEntry(e))
}
fmt.Fprintf(&buf, "]")
}
@ -80,6 +84,24 @@ 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 (f EntryFormatter) DescribeEntry(e pb.Entry) 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)
}
// DescribeMessage returns a concise human-readable description of a
// Message for debugging using the default formatter.
func DescribeMessage(m pb.Message) string {
return EntryFormatter(nil).DescribeMessage(m)
}
// DescribeEntry returns a concise human-readable description of an
// Entry for debugging using the default formatter.
func DescribeEntry(e pb.Entry) string {
return EntryFormatter(nil).DescribeEntry(e)
}

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)
if defaultFormatted != "1/2 EntryNormal \"hello\\x00world\"" {
t.Errorf("unexpected default output: %s", defaultFormatted)
}
customFormatted := testFormatter.DescribeEntry(entry)
if customFormatted != "1/2 EntryNormal HELLO\x00WORLD" {
t.Errorf("unexpected custom output: %s", customFormatted)
}
}