trace.go (2956B)
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 "sync" 28 "time" 29 30 "golang.org/x/net/trace" 31 ) 32 33 // EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package. 34 // This should only be set before any RPCs are sent or received by this program. 35 var EnableTracing bool 36 37 // methodFamily returns the trace family for the given method. 38 // It turns "/pkg.Service/GetFoo" into "pkg.Service". 39 func methodFamily(m string) string { 40 m = strings.TrimPrefix(m, "/") // remove leading slash 41 if i := strings.Index(m, "/"); i >= 0 { 42 m = m[:i] // remove everything from second slash 43 } 44 return m 45 } 46 47 // traceInfo contains tracing information for an RPC. 48 type traceInfo struct { 49 tr trace.Trace 50 firstLine firstLine 51 } 52 53 // firstLine is the first line of an RPC trace. 54 // It may be mutated after construction; remoteAddr specifically may change 55 // during client-side use. 56 type firstLine struct { 57 mu sync.Mutex 58 client bool // whether this is a client (outgoing) RPC 59 remoteAddr net.Addr 60 deadline time.Duration // may be zero 61 } 62 63 func (f *firstLine) SetRemoteAddr(addr net.Addr) { 64 f.mu.Lock() 65 f.remoteAddr = addr 66 f.mu.Unlock() 67 } 68 69 func (f *firstLine) String() string { 70 f.mu.Lock() 71 defer f.mu.Unlock() 72 73 var line bytes.Buffer 74 io.WriteString(&line, "RPC: ") 75 if f.client { 76 io.WriteString(&line, "to") 77 } else { 78 io.WriteString(&line, "from") 79 } 80 fmt.Fprintf(&line, " %v deadline:", f.remoteAddr) 81 if f.deadline != 0 { 82 fmt.Fprint(&line, f.deadline) 83 } else { 84 io.WriteString(&line, "none") 85 } 86 return line.String() 87 } 88 89 const truncateSize = 100 90 91 func truncate(x string, l int) string { 92 if l > len(x) { 93 return x 94 } 95 return x[:l] 96 } 97 98 // payload represents an RPC request or response payload. 99 type payload struct { 100 sent bool // whether this is an outgoing payload 101 msg interface{} // e.g. a proto.Message 102 // TODO(dsymonds): add stringifying info to codec, and limit how much we hold here? 103 } 104 105 func (p payload) String() string { 106 if p.sent { 107 return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize) 108 } 109 return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize) 110 } 111 112 type fmtStringer struct { 113 format string 114 a []interface{} 115 } 116 117 func (f *fmtStringer) String() string { 118 return fmt.Sprintf(f.format, f.a...) 119 } 120 121 type stringer string 122 123 func (s stringer) String() string { return string(s) }