grpc: add trace.EventLog to ClientConn.

This event log records events that are interesting for live debugging
of a gRPC client.  In particular, this records when a connection is
established, broken, and reestablished.  The log is displayed on the
HTTP endpoint /debug/events in the family named "grpc.ClientConn".

Tested using a version of the route guide client modified to serve
HTTP and block at the end of main.
This commit is contained in:
Sameer Ajmani
2015-08-09 23:07:37 -04:00
parent 18c359f6a9
commit 994fc85650

View File

@ -42,6 +42,7 @@ import (
"time" "time"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/net/trace"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/transport" "google.golang.org/grpc/transport"
@ -131,6 +132,7 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) {
} }
cc := &ClientConn{ cc := &ClientConn{
target: target, target: target,
events: trace.NewEventLog("grpc.ClientConn", target),
shutdownChan: make(chan struct{}), shutdownChan: make(chan struct{}),
} }
for _, opt := range opts { for _, opt := range opts {
@ -157,6 +159,7 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) {
// Start a goroutine connecting to the server asynchronously. // Start a goroutine connecting to the server asynchronously.
go func() { go func() {
if err := cc.resetTransport(false); err != nil { if err := cc.resetTransport(false); err != nil {
cc.events.Errorf("dial failed: %v", err)
grpclog.Printf("Failed to dial %s: %v; please retry.", target, err) grpclog.Printf("Failed to dial %s: %v; please retry.", target, err)
cc.Close() cc.Close()
return return
@ -206,6 +209,7 @@ type ClientConn struct {
authority string authority string
dopts dialOptions dopts dialOptions
shutdownChan chan struct{} shutdownChan chan struct{}
events trace.EventLog
mu sync.Mutex mu sync.Mutex
state ConnectivityState state ConnectivityState
@ -320,9 +324,11 @@ func (cc *ClientConn) resetTransport(closeTransport bool) error {
closeTransport = false closeTransport = false
time.Sleep(sleepTime) time.Sleep(sleepTime)
retries++ retries++
cc.events.Errorf("connection failed, will retry: %v", err)
grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target) grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
continue continue
} }
cc.events.Printf("connection established")
cc.mu.Lock() cc.mu.Lock()
if cc.state == Shutdown { if cc.state == Shutdown {
// cc.Close() has been invoked. // cc.Close() has been invoked.
@ -359,6 +365,7 @@ func (cc *ClientConn) transportMonitor() {
cc.mu.Unlock() cc.mu.Unlock()
if err := cc.resetTransport(true); err != nil { if err := cc.resetTransport(true); err != nil {
// The ClientConn is closing. // The ClientConn is closing.
cc.events.Printf("transport exiting: %v", err)
grpclog.Printf("grpc: ClientConn.transportMonitor exits due to: %v", err) grpclog.Printf("grpc: ClientConn.transportMonitor exits due to: %v", err)
return return
} }
@ -411,6 +418,7 @@ func (cc *ClientConn) Close() error {
} }
cc.state = Shutdown cc.state = Shutdown
cc.stateCV.Broadcast() cc.stateCV.Broadcast()
cc.events.Finish()
if cc.ready != nil { if cc.ready != nil {
close(cc.ready) close(cc.ready)
cc.ready = nil cc.ready = nil