blob: 07a2d26b3e77dd305cbc57afa4f9e3e8f5bbfe98 [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001/*
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
19package grpc
20
21import (
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.
35var EnableTracing bool
36
37// methodFamily returns the trace family for the given method.
38// It turns "/pkg.Service/GetFoo" into "pkg.Service".
39func 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 }
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070044 return m
45}
46
47// traceInfo contains tracing information for an RPC.
48type 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.
56type 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
63func (f *firstLine) SetRemoteAddr(addr net.Addr) {
64 f.mu.Lock()
65 f.remoteAddr = addr
66 f.mu.Unlock()
67}
68
69func (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
89const truncateSize = 100
90
91func 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.
99type 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
105func (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
112type fmtStringer struct {
113 format string
114 a []interface{}
115}
116
117func (f *fmtStringer) String() string {
118 return fmt.Sprintf(f.format, f.a...)
119}
120
121type stringer string
122
123func (s stringer) String() string { return string(s) }