TUN-2344: log more details: http2.Framer.ErrorDetail() if available, connectionID

This commit is contained in:
Nick Vollmar 2019-10-14 18:36:34 -05:00
parent a4b3ee5959
commit 4d2583edf5
2 changed files with 23 additions and 17 deletions

View File

@ -87,23 +87,28 @@ func (r *MuxReader) run(parentLogger *log.Entry) error {
for { for {
frame, err := r.f.ReadFrame() frame, err := r.f.ReadFrame()
if err != nil { if err != nil {
errLogger := logger.WithError(err)
if errorDetail := r.f.ErrorDetail(); errorDetail != nil {
errLogger = errLogger.WithField("errorDetail", errorDetail)
}
switch e := err.(type) { switch e := err.(type) {
case http2.StreamError: case http2.StreamError:
logger.WithError(err).Warn("stream error") errLogger.Warn("stream error")
r.streamError(e.StreamID, e.Code) r.streamError(e.StreamID, e.Code)
case http2.ConnectionError: case http2.ConnectionError:
logger.WithError(err).Warn("connection error") errLogger.Warn("connection error")
return r.connectionError(err) return r.connectionError(err)
default: default:
if isConnectionClosedError(err) { if isConnectionClosedError(err) {
if r.streams.Len() == 0 { if r.streams.Len() == 0 {
// don't log the error here -- that would just be extra noise
logger.Debug("shutting down") logger.Debug("shutting down")
return nil return nil
} }
logger.Warn("connection closed unexpectedly") errLogger.Warn("connection closed unexpectedly")
return err return err
} else { } else {
logger.WithError(err).Warn("frame read error") errLogger.Warn("frame read error")
return r.connectionError(err) return r.connectionError(err)
} }
} }

View File

@ -152,7 +152,7 @@ func ServeTunnelLoop(ctx context.Context,
connectedSignal *signal.Signal, connectedSignal *signal.Signal,
u uuid.UUID, u uuid.UUID,
) error { ) error {
logger := config.Logger connectionLogger := config.Logger.WithField("connectionID", connectionID)
config.Metrics.incrementHaConnections() config.Metrics.incrementHaConnections()
defer config.Metrics.decrementHaConnections() defer config.Metrics.decrementHaConnections()
backoff := BackoffHandler{MaxRetries: config.Retries} backoff := BackoffHandler{MaxRetries: config.Retries}
@ -165,10 +165,10 @@ func ServeTunnelLoop(ctx context.Context,
// Ensure the above goroutine will terminate if we return without connecting // Ensure the above goroutine will terminate if we return without connecting
defer connectedFuse.Fuse(false) defer connectedFuse.Fuse(false)
for { for {
err, recoverable := ServeTunnel(ctx, config, addr, connectionID, connectedFuse, &backoff, u) err, recoverable := ServeTunnel(ctx, config, connectionLogger, addr, connectionID, connectedFuse, &backoff, u)
if recoverable { if recoverable {
if duration, ok := backoff.GetBackoffDuration(ctx); ok { if duration, ok := backoff.GetBackoffDuration(ctx); ok {
logger.Infof("Retrying in %s seconds", duration) connectionLogger.Infof("Retrying in %s seconds", duration)
backoff.Backoff(ctx) backoff.Backoff(ctx)
continue continue
} }
@ -180,6 +180,7 @@ func ServeTunnelLoop(ctx context.Context,
func ServeTunnel( func ServeTunnel(
ctx context.Context, ctx context.Context,
config *TunnelConfig, config *TunnelConfig,
logger *log.Entry,
addr *net.TCPAddr, addr *net.TCPAddr,
connectionID uint8, connectionID uint8,
connectedFuse *h2mux.BooleanFuse, connectedFuse *h2mux.BooleanFuse,
@ -199,7 +200,6 @@ func ServeTunnel(
}() }()
connectionTag := uint8ToString(connectionID) connectionTag := uint8ToString(connectionID)
logger := config.Logger.WithField("connectionID", connectionTag)
// additional tags to send other than hostname which is set in cloudflared main package // additional tags to send other than hostname which is set in cloudflared main package
tags := make(map[string]string) tags := make(map[string]string)
@ -208,7 +208,7 @@ func ServeTunnel(
// Returns error from parsing the origin URL or handshake errors // Returns error from parsing the origin URL or handshake errors
handler, originLocalIP, err := NewTunnelHandler(ctx, config, addr.String(), connectionID) handler, originLocalIP, err := NewTunnelHandler(ctx, config, addr.String(), connectionID)
if err != nil { if err != nil {
errLog := config.Logger.WithError(err) errLog := logger.WithError(err)
switch err.(type) { switch err.(type) {
case dialError: case dialError:
errLog.Error("Unable to dial edge") errLog.Error("Unable to dial edge")
@ -224,7 +224,7 @@ func ServeTunnel(
errGroup, serveCtx := errgroup.WithContext(ctx) errGroup, serveCtx := errgroup.WithContext(ctx)
errGroup.Go(func() error { errGroup.Go(func() error {
err := RegisterTunnel(serveCtx, handler.muxer, config, connectionID, originLocalIP, u) err := RegisterTunnel(serveCtx, handler.muxer, config, logger, connectionID, originLocalIP, u)
if err == nil { if err == nil {
connectedFuse.Fuse(true) connectedFuse.Fuse(true)
backoff.SetGracePeriod() backoff.SetGracePeriod()
@ -302,6 +302,7 @@ func RegisterTunnel(
ctx context.Context, ctx context.Context,
muxer *h2mux.Muxer, muxer *h2mux.Muxer,
config *TunnelConfig, config *TunnelConfig,
logger *log.Entry,
connectionID uint8, connectionID uint8,
originLocalIP string, originLocalIP string,
uuid uuid.UUID, uuid uuid.UUID,
@ -333,13 +334,13 @@ func RegisterTunnel(
config.Hostname, config.Hostname,
config.RegistrationOptions(connectionID, originLocalIP, uuid), config.RegistrationOptions(connectionID, originLocalIP, uuid),
) )
LogServerInfo(serverInfoPromise.Result(), connectionID, config.Metrics, config.Logger) LogServerInfo(serverInfoPromise.Result(), connectionID, config.Metrics, logger)
if err != nil { if err != nil {
// RegisterTunnel RPC failure // RegisterTunnel RPC failure
return newClientRegisterTunnelError(err, config.Metrics.regFail) return newClientRegisterTunnelError(err, config.Metrics.regFail)
} }
for _, logLine := range registration.LogLines { for _, logLine := range registration.LogLines {
config.Logger.Info(logLine) logger.Info(logLine)
} }
if regErr := processRegisterTunnelError(registration.Err, registration.PermanentFailure, config.Metrics); regErr != nil { if regErr := processRegisterTunnelError(registration.Err, registration.PermanentFailure, config.Metrics); regErr != nil {
@ -348,24 +349,24 @@ func RegisterTunnel(
if registration.TunnelID != "" { if registration.TunnelID != "" {
config.Metrics.tunnelsHA.AddTunnelID(connectionID, registration.TunnelID) config.Metrics.tunnelsHA.AddTunnelID(connectionID, registration.TunnelID)
config.Logger.Infof("Each HA connection's tunnel IDs: %v", config.Metrics.tunnelsHA.String()) logger.Infof("Each HA connection's tunnel IDs: %v", config.Metrics.tunnelsHA.String())
} }
// Print out the user's trial zone URL in a nice box (if they requested and got one) // Print out the user's trial zone URL in a nice box (if they requested and got one)
if isTrialTunnel := config.Hostname == ""; isTrialTunnel { if isTrialTunnel := config.Hostname == ""; isTrialTunnel {
if url, err := url.Parse(registration.Url); err == nil { if url, err := url.Parse(registration.Url); err == nil {
for _, line := range asciiBox(trialZoneMsg(url.String()), 2) { for _, line := range asciiBox(trialZoneMsg(url.String()), 2) {
config.Logger.Infoln(line) logger.Infoln(line)
} }
} else { } else {
config.Logger.Errorln("Failed to connect tunnel, please try again.") logger.Errorln("Failed to connect tunnel, please try again.")
return fmt.Errorf("empty URL in response from Cloudflare edge") return fmt.Errorf("empty URL in response from Cloudflare edge")
} }
} }
config.Metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc() config.Metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc()
config.Logger.Infof("Route propagating, it may take up to 1 minute for your new route to become functional") logger.Infof("Route propagating, it may take up to 1 minute for your new route to become functional")
return nil return nil
} }
@ -421,7 +422,7 @@ func LogServerInfo(
promise tunnelrpc.ServerInfo_Promise, promise tunnelrpc.ServerInfo_Promise,
connectionID uint8, connectionID uint8,
metrics *TunnelMetrics, metrics *TunnelMetrics,
logger *log.Logger, logger *log.Entry,
) { ) {
serverInfoMessage, err := promise.Struct() serverInfoMessage, err := promise.Struct()
if err != nil { if err != nil {