Repository: grpc/grpc-go
File: clientconn.go (Go)

Code before:
func (ac *addrConn) securityLevel() string {
	var secLevel string
	if ac.transport == nil {
		secLevel, _ = ac.curAddr.Attributes.Value(securityLevelKey{}).(string)
		return secLevel
	}
	authInfo := ac.transport.AuthInfo()
	if ci, ok := authInfo.(interface {
		GetCommonAuthInfo() credentials.CommonAuthInfo
	}); ok {
		secLevel = ci.GetCommonAuthInfo().SecurityLevel.String()
		ac.curAddr.Attributes = ac.curAddr.Attributes.WithValue(securityLevelKey{}, secLevel)
	}
	return secLevel
}

// tryAllAddrs tries to create a connection to the addresses, and stop when at
// the first successful one. It returns an error if no address was successfully
// connected, or updates ac appropriately with the new transport.
func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, connectDeadline time.Time) error {
	var firstConnErr error
	for _, addr := range addrs {
		ac.channelz.ChannelMetrics.Target.Store(&addr.Addr)
		if ctx.Err() != nil {
			return errConnClosing
		}
		ac.mu.Lock()

		ac.cc.mu.RLock()
		ac.dopts.copts.KeepaliveParams = ac.cc.keepaliveParams
		ac.cc.mu.RUnlock()

		copts := ac.dopts.copts
		if ac.scopts.CredsBundle != nil {
			copts.CredsBundle = ac.scopts.CredsBundle
		}
		ac.mu.Unlock()

		channelz.Infof(logger, ac.channelz, "Subchannel picks a new address %q to connect", addr.Addr)

		err := ac.createTransport(ctx, addr, copts, connectDeadline)
		if err == nil {
			return nil
		}
		if firstConnErr == nil {
			firstConnErr = err
		}
		ac.cc.updateConnectionError(err)
	}

	// Couldn't connect to any address.

Review comment (security):
If there is a valid security_level when the connection is established (and the upDown counter is being incremented), and there is no valid security_level when the connection is disconnected (and the upDown counter is being decremented), does it affect the metric in anyway since the labels are going to be different on the two calls?

Also, an empty string is not a valid value for the security level as per the gRFC:
```
Allowed values - "none", "integrity_only" and "privacy_and_integrity".
```

So, would it make sense to drop the nil check here and instead pass `none` from where the disconnections are handled? Or if the change in the optional labels matters, would we have to store the security_level in the `addrConn` when the connection is established so that we can use the same value when the connection is terminated?

Code after:
	ac.mu.Unlock()
}

// updateTelemetryLabelsLocked calculates and caches the telemetry labels based on the
// first address in addrConn.
func (ac *addrConn) updateTelemetryLabelsLocked() {
	labelsFunc, ok := internal.AddressToTelemetryLabels.(func(resolver.Address) map[string]string)
	if !ok || len(ac.addrs) == 0 {
		// Reset defaults
		ac.localityLabel = ""
		ac.backendServiceLabel = ""
		return
	}
	labels := labelsFunc(ac.addrs[0])
	ac.localityLabel = labels["grpc.lb.locality"]
	ac.backendServiceLabel = labels["grpc.lb.backend_service"]
}

type securityLevelKey struct{}

func (ac *addrConn) securityLevelLocked() string {
	var secLevel string
	// During disconnection, ac.transport is nil. Fall back to the security level
	// stored in the current address during connection.
	if ac.transport == nil {
		secLevel, _ = ac.curAddr.Attributes.Value(securityLevelKey{}).(string)
		return secLevel
	}
	authInfo := ac.transport.Peer().AuthInfo
	if ci, ok := authInfo.(interface {
		GetCommonAuthInfo() credentials.CommonAuthInfo
	}); ok {
		secLevel = ci.GetCommonAuthInfo().SecurityLevel.String()
		// Store the security level in the current address' attributes so
		// that it remains available for disconnection metrics after the
		// transport is closed.
		ac.curAddr.Attributes = ac.curAddr.Attributes.WithValue(securityLevelKey{}, secLevel)
	}
	return secLevel
}

// tryAllAddrs tries to create a connection to the addresses, and stop when at
// the first successful one. It returns an error if no address was successfully
// connected, or updates ac appropriately with the new transport.
func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, connectDeadline time.Time) error {
	var firstConnErr error
	for _, addr := range addrs {
		ac.channelz.ChannelMetrics.Target.Store(&addr.Addr)
		if ctx.Err() != nil {
			return errConnClosing
		}