]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
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. | |
107c1cdb | 34 | var EnableTracing bool |
15c0b25d AP |
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 | ||
107c1cdb ND |
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 | ||
15c0b25d AP |
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 { | |
107c1cdb | 97 | return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize) |
15c0b25d | 98 | } |
107c1cdb | 99 | return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize) |
15c0b25d AP |
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) } |