| /* | |
| * | |
| * Copyright 2015 gRPC authors. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| */ | |
| package grpc | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io" | |
| "net" | |
| "strings" | |
| "sync" | |
| "time" | |
| ) | |
| // EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package. | |
| // This should only be set before any RPCs are sent or received by this program. | |
| var EnableTracing bool | |
| // methodFamily returns the trace family for the given method. | |
| // It turns "/pkg.Service/GetFoo" into "pkg.Service". | |
| func methodFamily(m string) string { | |
| m = strings.TrimPrefix(m, "/") // remove leading slash | |
| if i := strings.Index(m, "/"); i >= 0 { | |
| m = m[:i] // remove everything from second slash | |
| } | |
| return m | |
| } | |
| // traceEventLog mirrors golang.org/x/net/trace.EventLog. | |
| // | |
| // It exists in order to avoid importing x/net/trace on grpcnotrace builds. | |
| type traceEventLog interface { | |
| Printf(format string, a ...any) | |
| Errorf(format string, a ...any) | |
| Finish() | |
| } | |
| // traceLog mirrors golang.org/x/net/trace.Trace. | |
| // | |
| // It exists in order to avoid importing x/net/trace on grpcnotrace builds. | |
| type traceLog interface { | |
| LazyLog(x fmt.Stringer, sensitive bool) | |
| LazyPrintf(format string, a ...any) | |
| SetError() | |
| SetRecycler(f func(any)) | |
| SetTraceInfo(traceID, spanID uint64) | |
| SetMaxEvents(m int) | |
| Finish() | |
| } | |
| // traceInfo contains tracing information for an RPC. | |
| type traceInfo struct { | |
| tr traceLog | |
| firstLine firstLine | |
| } | |
| // firstLine is the first line of an RPC trace. | |
| // It may be mutated after construction; remoteAddr specifically may change | |
| // during client-side use. | |
| type firstLine struct { | |
| mu sync.Mutex | |
| client bool // whether this is a client (outgoing) RPC | |
| remoteAddr net.Addr | |
| deadline time.Duration // may be zero | |
| } | |
| func (f *firstLine) SetRemoteAddr(addr net.Addr) { | |
| f.mu.Lock() | |
| f.remoteAddr = addr | |
| f.mu.Unlock() | |
| } | |
| func (f *firstLine) String() string { | |
| f.mu.Lock() | |
| defer f.mu.Unlock() | |
| var line bytes.Buffer | |
| io.WriteString(&line, "RPC: ") | |
| if f.client { | |
| io.WriteString(&line, "to") | |
| } else { | |
| io.WriteString(&line, "from") | |
| } | |
| fmt.Fprintf(&line, " %v deadline:", f.remoteAddr) | |
| if f.deadline != 0 { | |
| fmt.Fprint(&line, f.deadline) | |
| } else { | |
| io.WriteString(&line, "none") | |
| } | |
| return line.String() | |
| } | |
| const truncateSize = 100 | |
| func truncate(x string, l int) string { | |
| if l > len(x) { | |
| return x | |
| } | |
| return x[:l] | |
| } | |
| // payload represents an RPC request or response payload. | |
| type payload struct { | |
| sent bool // whether this is an outgoing payload | |
| msg any // e.g. a proto.Message | |
| // TODO(dsymonds): add stringifying info to codec, and limit how much we hold here? | |
| } | |
| func (p payload) String() string { | |
| if p.sent { | |
| return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize) | |
| } | |
| return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize) | |
| } | |
| type fmtStringer struct { | |
| format string | |
| a []any | |
| } | |
| func (f *fmtStringer) String() string { | |
| return fmt.Sprintf(f.format, f.a...) | |
| } | |
| type stringer string | |
| func (s stringer) String() string { return string(s) } |