Add -vv and move estimated size to this new very verbose format

This commit is contained in:
Sergei Vorobev 2020-08-07 23:06:25 -07:00
parent 60926d9bde
commit 3a2ce54ef4
4 changed files with 43 additions and 19 deletions

View File

@ -135,6 +135,8 @@ var (
When describing messages, show a template of input data.`)) When describing messages, show a template of input data.`))
verbose = flags.Bool("v", false, prettify(` verbose = flags.Bool("v", false, prettify(`
Enable verbose output.`)) Enable verbose output.`))
veryVerbose = flags.Bool("vv", false, prettify(`
Enable very verbose output.`))
serverName = flags.String("servername", "", prettify(` serverName = flags.String("servername", "", prettify(`
Override server name when validating TLS certificate. This flag is Override server name when validating TLS certificate. This flag is
ignored if -plaintext or -insecure is used. ignored if -plaintext or -insecure is used.
@ -316,6 +318,14 @@ func main() {
invoke = true invoke = true
} }
verbosityLevel := 0
if *verbose {
verbosityLevel = 1
}
if *veryVerbose {
verbosityLevel = 2
}
var symbol string var symbol string
if invoke { if invoke {
if len(args) == 0 { if len(args) == 0 {
@ -651,7 +661,7 @@ func main() {
// if not verbose output, then also include record delimiters // if not verbose output, then also include record delimiters
// between each message, so output could potentially be piped // between each message, so output could potentially be piped
// to another grpcurl process // to another grpcurl process
includeSeparators := !*verbose includeSeparators := verbosityLevel == 0
options := grpcurl.FormatOptions{ options := grpcurl.FormatOptions{
EmitJSONDefaultFields: *emitDefaults, EmitJSONDefaultFields: *emitDefaults,
IncludeTextSeparator: includeSeparators, IncludeTextSeparator: includeSeparators,
@ -661,7 +671,7 @@ func main() {
if err != nil { if err != nil {
fail(err, "Failed to construct request parser and formatter for %q", *format) fail(err, "Failed to construct request parser and formatter for %q", *format)
} }
h := grpcurl.NewDefaultEventHandler(os.Stdout, descSource, formatter, *verbose) h := grpcurl.NewDefaultEventHandler(os.Stdout, descSource, formatter, verbosityLevel)
err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next) err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next)
if err != nil { if err != nil {
@ -676,7 +686,7 @@ func main() {
if h.NumResponses != 1 { if h.NumResponses != 1 {
respSuffix = "s" respSuffix = "s"
} }
if *verbose { if verbosityLevel > 0 {
fmt.Printf("Sent %d request%s and received %d response%s\n", reqCount, reqSuffix, h.NumResponses, respSuffix) fmt.Printf("Sent %d request%s and received %d response%s\n", reqCount, reqSuffix, h.NumResponses, respSuffix)
} }
if h.Status.Code() != codes.OK { if h.Status.Code() != codes.OK {

View File

@ -412,7 +412,10 @@ type DefaultEventHandler struct {
out io.Writer out io.Writer
descSource DescriptorSource descSource DescriptorSource
formatter func(proto.Message) (string, error) formatter func(proto.Message) (string, error)
verbose bool // 0 = default
// 1 = verbose
// 2 = very verbose
verbosityLevel int
// NumResponses is the number of responses that have been received. // NumResponses is the number of responses that have been received.
NumResponses int NumResponses int
@ -424,19 +427,19 @@ type DefaultEventHandler struct {
// NewDefaultEventHandler returns an InvocationEventHandler that logs events to // NewDefaultEventHandler returns an InvocationEventHandler that logs events to
// the given output. If verbose is true, all events are logged. Otherwise, only // the given output. If verbose is true, all events are logged. Otherwise, only
// response messages are logged. // response messages are logged.
func NewDefaultEventHandler(out io.Writer, descSource DescriptorSource, formatter Formatter, verbose bool) *DefaultEventHandler { func NewDefaultEventHandler(out io.Writer, descSource DescriptorSource, formatter Formatter, verbosityLevel int) *DefaultEventHandler {
return &DefaultEventHandler{ return &DefaultEventHandler{
out: out, out: out,
descSource: descSource, descSource: descSource,
formatter: formatter, formatter: formatter,
verbose: verbose, verbosityLevel: verbosityLevel,
} }
} }
var _ InvocationEventHandler = (*DefaultEventHandler)(nil) var _ InvocationEventHandler = (*DefaultEventHandler)(nil)
func (h *DefaultEventHandler) OnResolveMethod(md *desc.MethodDescriptor) { func (h *DefaultEventHandler) OnResolveMethod(md *desc.MethodDescriptor) {
if h.verbose { if h.verbosityLevel > 0 {
txt, err := GetDescriptorText(md, h.descSource) txt, err := GetDescriptorText(md, h.descSource)
if err == nil { if err == nil {
fmt.Fprintf(h.out, "\nResolved method descriptor:\n%s\n", txt) fmt.Fprintf(h.out, "\nResolved method descriptor:\n%s\n", txt)
@ -445,21 +448,23 @@ func (h *DefaultEventHandler) OnResolveMethod(md *desc.MethodDescriptor) {
} }
func (h *DefaultEventHandler) OnSendHeaders(md metadata.MD) { func (h *DefaultEventHandler) OnSendHeaders(md metadata.MD) {
if h.verbose { if h.verbosityLevel > 0 {
fmt.Fprintf(h.out, "\nRequest metadata to send:\n%s\n", MetadataToString(md)) fmt.Fprintf(h.out, "\nRequest metadata to send:\n%s\n", MetadataToString(md))
} }
} }
func (h *DefaultEventHandler) OnReceiveHeaders(md metadata.MD) { func (h *DefaultEventHandler) OnReceiveHeaders(md metadata.MD) {
if h.verbose { if h.verbosityLevel > 0 {
fmt.Fprintf(h.out, "\nResponse headers received:\n%s\n", MetadataToString(md)) fmt.Fprintf(h.out, "\nResponse headers received:\n%s\n", MetadataToString(md))
} }
} }
func (h *DefaultEventHandler) OnReceiveResponse(resp proto.Message) { func (h *DefaultEventHandler) OnReceiveResponse(resp proto.Message) {
h.NumResponses++ h.NumResponses++
if h.verbose { if h.verbosityLevel > 1 {
fmt.Fprintf(h.out, "\nResponse size (bytes): %d\n", proto.Size(resp)) fmt.Fprintf(h.out, "\nEstimated response size: %d bytes\n", proto.Size(resp))
}
if h.verbosityLevel > 0 {
fmt.Fprint(h.out, "\nResponse contents:\n") fmt.Fprint(h.out, "\nResponse contents:\n")
} }
if respStr, err := h.formatter(resp); err != nil { if respStr, err := h.formatter(resp); err != nil {
@ -471,7 +476,7 @@ func (h *DefaultEventHandler) OnReceiveResponse(resp proto.Message) {
func (h *DefaultEventHandler) OnReceiveTrailers(stat *status.Status, md metadata.MD) { func (h *DefaultEventHandler) OnReceiveTrailers(stat *status.Status, md metadata.MD) {
h.Status = stat h.Status = stat
if h.verbose { if h.verbosityLevel > 0 {
fmt.Fprintf(h.out, "\nResponse trailers received:\n%s\n", MetadataToString(md)) fmt.Fprintf(h.out, "\nResponse trailers received:\n%s\n", MetadataToString(md))
} }
} }

View File

@ -120,12 +120,14 @@ func TestHandler(t *testing.T) {
for _, format := range []Format{FormatJSON, FormatText} { for _, format := range []Format{FormatJSON, FormatText} {
for _, numMessages := range []int{1, 3} { for _, numMessages := range []int{1, 3} {
for _, verbose := range []bool{true, false} { for verbosityLevel := 0; verbosityLevel <= 2; verbosityLevel++ {
name := fmt.Sprintf("%s, %d message(s)", format, numMessages) name := fmt.Sprintf("%s, %d message(s)", format, numMessages)
if verbose { if verbosityLevel > 0 {
name += ", verbose" name += fmt.Sprintf(", verbosityLevel=%d", verbosityLevel)
} }
verbose := verbosityLevel > 0
_, formatter, err := RequestParserAndFormatter(format, source, nil, FormatOptions{IncludeTextSeparator: !verbose}) _, formatter, err := RequestParserAndFormatter(format, source, nil, FormatOptions{IncludeTextSeparator: !verbose})
if err != nil { if err != nil {
t.Errorf("Failed to create parser and formatter: %v", err) t.Errorf("Failed to create parser and formatter: %v", err)
@ -133,7 +135,7 @@ func TestHandler(t *testing.T) {
} }
var buf bytes.Buffer var buf bytes.Buffer
h := NewDefaultEventHandler(&buf, source, formatter, verbose) h := NewDefaultEventHandler(&buf, source, formatter, verbosityLevel)
h.OnResolveMethod(md) h.OnResolveMethod(md)
h.OnSendHeaders(reqHeaders) h.OnSendHeaders(reqHeaders)
@ -148,6 +150,9 @@ func TestHandler(t *testing.T) {
expectedOutput += verbosePrefix expectedOutput += verbosePrefix
} }
for i := 0; i < numMessages; i++ { for i := 0; i < numMessages; i++ {
if verbosityLevel > 1 {
expectedOutput += verboseResponseSize
}
if verbose { if verbose {
expectedOutput += verboseResponseHeader expectedOutput += verboseResponseHeader
} }
@ -226,6 +231,9 @@ Response trailers received:
a: 1 a: 1
b: 2 b: 2
c: 3 c: 3
`
verboseResponseSize = `
Estimated response size: 100 bytes
` `
verboseResponseHeader = ` verboseResponseHeader = `
Response contents: Response contents:

1
go.sum
View File

@ -365,6 +365,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=