Home | History | Annotate | Download | only in grpc
      1 /*
      2  *
      3  * Copyright 2015 gRPC authors.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  */
     18 
     19 package grpc
     20 
     21 import (
     22 	"bytes"
     23 	"fmt"
     24 	"io"
     25 	"net"
     26 	"strings"
     27 	"time"
     28 
     29 	"golang.org/x/net/trace"
     30 )
     31 
     32 // EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package.
     33 // This should only be set before any RPCs are sent or received by this program.
     34 var EnableTracing bool
     35 
     36 // methodFamily returns the trace family for the given method.
     37 // It turns "/pkg.Service/GetFoo" into "pkg.Service".
     38 func methodFamily(m string) string {
     39 	m = strings.TrimPrefix(m, "/") // remove leading slash
     40 	if i := strings.Index(m, "/"); i >= 0 {
     41 		m = m[:i] // remove everything from second slash
     42 	}
     43 	if i := strings.LastIndex(m, "."); i >= 0 {
     44 		m = m[i+1:] // cut down to last dotted component
     45 	}
     46 	return m
     47 }
     48 
     49 // traceInfo contains tracing information for an RPC.
     50 type traceInfo struct {
     51 	tr        trace.Trace
     52 	firstLine firstLine
     53 }
     54 
     55 // firstLine is the first line of an RPC trace.
     56 type firstLine struct {
     57 	client     bool // whether this is a client (outgoing) RPC
     58 	remoteAddr net.Addr
     59 	deadline   time.Duration // may be zero
     60 }
     61 
     62 func (f *firstLine) String() string {
     63 	var line bytes.Buffer
     64 	io.WriteString(&line, "RPC: ")
     65 	if f.client {
     66 		io.WriteString(&line, "to")
     67 	} else {
     68 		io.WriteString(&line, "from")
     69 	}
     70 	fmt.Fprintf(&line, " %v deadline:", f.remoteAddr)
     71 	if f.deadline != 0 {
     72 		fmt.Fprint(&line, f.deadline)
     73 	} else {
     74 		io.WriteString(&line, "none")
     75 	}
     76 	return line.String()
     77 }
     78 
     79 const truncateSize = 100
     80 
     81 func truncate(x string, l int) string {
     82 	if l > len(x) {
     83 		return x
     84 	}
     85 	return x[:l]
     86 }
     87 
     88 // payload represents an RPC request or response payload.
     89 type payload struct {
     90 	sent bool        // whether this is an outgoing payload
     91 	msg  interface{} // e.g. a proto.Message
     92 	// TODO(dsymonds): add stringifying info to codec, and limit how much we hold here?
     93 }
     94 
     95 func (p payload) String() string {
     96 	if p.sent {
     97 		return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize)
     98 	}
     99 	return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize)
    100 }
    101 
    102 type fmtStringer struct {
    103 	format string
    104 	a      []interface{}
    105 }
    106 
    107 func (f *fmtStringer) String() string {
    108 	return fmt.Sprintf(f.format, f.a...)
    109 }
    110 
    111 type stringer string
    112 
    113 func (s stringer) String() string { return string(s) }
    114