Skip to content

Commit 627d2ca

Browse files
committed
a89 wrr changes adding backend service to per call metrics
a94 subchannel metrics with labels
1 parent e816736 commit 627d2ca

File tree

15 files changed

+484
-31
lines changed

15 files changed

+484
-31
lines changed

balancer/pickfirst/metrics_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,31 @@ func (s) TestPickFirstMetrics(t *testing.T) {
102102
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
103103
}
104104

105+
//Checking for subchannel metrics as well
106+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_succeeded"); got != 1 {
107+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_succeeded", got, 1)
108+
}
109+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_failed"); got != 0 {
110+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_failed", got, 0)
111+
}
112+
if got, _ := tmr.Metric("grpc.subchannel.disconnections"); got != 0 {
113+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.disconnections", got, 0)
114+
}
115+
if got, _ := tmr.Metric("grpc.subchannel.open_connections"); got != 1 {
116+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.open_connections", got, 1)
117+
}
118+
105119
ss.Stop()
106120
testutils.AwaitState(ctx, t, cc, connectivity.Idle)
107121
if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 1 {
108122
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 1)
109123
}
124+
if got, _ := tmr.Metric("grpc.subchannel.disconnections"); got != 1 {
125+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.disconnections", got, 1)
126+
}
127+
if got, _ := tmr.Metric("grpc.subchannel.open_connections"); got != -1 {
128+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.open_connections", got, -1)
129+
}
110130
}
111131

112132
// TestPickFirstMetricsFailure tests the connection attempts failed metric. It

balancer/pickfirst/pickfirst_ext_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"encoding/json"
2424
"errors"
2525
"fmt"
26+
"slices"
2627
"strings"
2728
"sync"
2829
"testing"
@@ -1946,6 +1947,20 @@ func (s) TestPickFirstLeaf_HappyEyeballs_TF_AfterEndOfList(t *testing.T) {
19461947
if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
19471948
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
19481949
}
1950+
1951+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_succeeded"); got != 0 {
1952+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_succeeded", got, 0)
1953+
}
1954+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_failed"); got != 1 {
1955+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_failed", got, 1)
1956+
}
1957+
expectedLabels := []string{"whatever:///test.server", "", "{region=\"\", zone=\"\", sub_zone=\"\"}"}
1958+
if detail, _ := tmr.MetricDetail("grpc.subchannel.connection_attempts_failed"); !slices.Equal(detail.LabelVals, expectedLabels) {
1959+
t.Errorf("Unexpected label values for metric %v, got: %v, want %v", "grpc.subchannel.connection_attempts_failed", detail.LabelVals, expectedLabels)
1960+
}
1961+
if got, _ := tmr.Metric("grpc.subchannel.disconnections"); got != 0 {
1962+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.disconnections", got, 0)
1963+
}
19491964
}
19501965

19511966
// Test verifies that pickfirst attempts to connect to the second backend once
@@ -2006,6 +2021,27 @@ func (s) TestPickFirstLeaf_HappyEyeballs_TriggerConnectionDelay(t *testing.T) {
20062021
if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
20072022
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
20082023
}
2024+
2025+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_succeeded"); got != 1 {
2026+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_succeeded", got, 1)
2027+
}
2028+
expectedLabels := []string{"whatever:///test.server", "", "{region=\"\", zone=\"\", sub_zone=\"\"}"}
2029+
if got, _ := tmr.MetricDetail("grpc.subchannel.connection_attempts_succeeded"); !slices.Equal(got.LabelVals, expectedLabels) {
2030+
t.Errorf("Unexpected data for metric %v, got: %s, want: %s", "grpc.subchannel.connection_attempts_succeeded", got.LabelVals, expectedLabels)
2031+
}
2032+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_failed"); got != 0 {
2033+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_failed", got, 0)
2034+
}
2035+
if got, _ := tmr.Metric("grpc.subchannel.disconnections"); got != 0 {
2036+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.disconnections", got, 0)
2037+
}
2038+
if got, _ := tmr.Metric("grpc.subchannel.open_connections"); got != 1 {
2039+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.open_connections", got, 1)
2040+
}
2041+
expectedLabels = []string{"whatever:///test.server", "", "NoSecurity", "{region=\"\", zone=\"\", sub_zone=\"\"}"}
2042+
if got, _ := tmr.MetricDetail("grpc.subchannel.open_connections"); !slices.Equal(got.LabelVals, expectedLabels) {
2043+
t.Errorf("Unexpected data for metric %v, got: %s, want: %s", "grpc.subchannel.open_connections", got.LabelVals, expectedLabels)
2044+
}
20092045
}
20102046

20112047
// Test tests the pickfirst balancer by causing a SubConn to fail and then
@@ -2057,6 +2093,13 @@ func (s) TestPickFirstLeaf_HappyEyeballs_TF_ThenTimerFires(t *testing.T) {
20572093
if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_failed"); got != 1 {
20582094
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_failed", got, 1)
20592095
}
2096+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_failed"); got != 1 {
2097+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_failed", got, 1)
2098+
}
2099+
expectedLabels := []string{"whatever:///test.server", "", "{region=\"\", zone=\"\", sub_zone=\"\"}"}
2100+
if got, _ := tmr.MetricDetail("grpc.subchannel.connection_attempts_failed"); !slices.Equal(got.LabelVals, expectedLabels) {
2101+
t.Errorf("Unexpected data for metric %v, got: %s, want: %s", "grpc.subchannel.connection_attempts_failed", got.LabelVals, expectedLabels)
2102+
}
20602103
if holds[2].IsStarted() != false {
20612104
t.Fatalf("Server %d with address %q contacted unexpectedly", 2, addrs[2])
20622105
}
@@ -2080,6 +2123,17 @@ func (s) TestPickFirstLeaf_HappyEyeballs_TF_ThenTimerFires(t *testing.T) {
20802123
if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
20812124
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
20822125
}
2126+
2127+
if got, _ := tmr.Metric("grpc.subchannel.connection_attempts_succeeded"); got != 1 {
2128+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.connection_attempts_succeeded", got, 1)
2129+
}
2130+
expectedLabels = []string{"whatever:///test.server", "", "{region=\"\", zone=\"\", sub_zone=\"\"}"}
2131+
if got, _ := tmr.MetricDetail("grpc.subchannel.connection_attempts_succeeded"); !slices.Equal(got.LabelVals, expectedLabels) {
2132+
t.Errorf("Unexpected data for metric %v, got: %s, want: %s", "grpc.subchannel.connection_attempts_succeeded", got.LabelVals, expectedLabels)
2133+
}
2134+
if got, _ := tmr.Metric("grpc.subchannel.disconnections"); got != 0 {
2135+
t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.subchannel.disconnections", got, 0)
2136+
}
20832137
}
20842138

20852139
func (s) TestPickFirstLeaf_InterleavingIPV4Preferred(t *testing.T) {

balancer/weightedroundrobin/balancer.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import (
4646
"google.golang.org/grpc/internal/grpclog"
4747
"google.golang.org/grpc/internal/grpcsync"
4848
iserviceconfig "google.golang.org/grpc/internal/serviceconfig"
49+
"google.golang.org/grpc/internal/xds/balancer/clusterimpl"
4950
"google.golang.org/grpc/orca"
5051
"google.golang.org/grpc/resolver"
5152
"google.golang.org/grpc/serviceconfig"
@@ -62,7 +63,7 @@ var (
6263
Description: "EXPERIMENTAL. Number of scheduler updates in which there were not enough endpoints with valid weight, which caused the WRR policy to fall back to RR behavior.",
6364
Unit: "{update}",
6465
Labels: []string{"grpc.target"},
65-
OptionalLabels: []string{"grpc.lb.locality"},
66+
OptionalLabels: []string{"grpc.lb.locality", "grpc.lb.backend_service"},
6667
Default: false,
6768
})
6869

@@ -71,7 +72,7 @@ var (
7172
Description: "EXPERIMENTAL. Number of endpoints from each scheduler update that don't yet have usable weight information (i.e., either the load report has not yet been received, or it is within the blackout period).",
7273
Unit: "{endpoint}",
7374
Labels: []string{"grpc.target"},
74-
OptionalLabels: []string{"grpc.lb.locality"},
75+
OptionalLabels: []string{"grpc.lb.locality", "grpc.lb.backend_service"},
7576
Default: false,
7677
})
7778

@@ -80,15 +81,15 @@ var (
8081
Description: "EXPERIMENTAL. Number of endpoints from each scheduler update whose latest weight is older than the expiration period.",
8182
Unit: "{endpoint}",
8283
Labels: []string{"grpc.target"},
83-
OptionalLabels: []string{"grpc.lb.locality"},
84+
OptionalLabels: []string{"grpc.lb.locality", "grpc.lb.backend_service"},
8485
Default: false,
8586
})
8687
endpointWeightsMetric = estats.RegisterFloat64Histo(estats.MetricDescriptor{
8788
Name: "grpc.lb.wrr.endpoint_weights",
8889
Description: "EXPERIMENTAL. Weight of each endpoint, recorded on every scheduler update. Endpoints without usable weights will be recorded as weight 0.",
8990
Unit: "{endpoint}",
9091
Labels: []string{"grpc.target"},
91-
OptionalLabels: []string{"grpc.lb.locality"},
92+
OptionalLabels: []string{"grpc.lb.locality", "grpc.lb.backend_service"},
9293
Default: false,
9394
})
9495
)
@@ -173,6 +174,7 @@ func (b *wrrBalancer) updateEndpointsLocked(endpoints []resolver.Endpoint) {
173174
metricsRecorder: b.metricsRecorder,
174175
target: b.target,
175176
locality: b.locality,
177+
cluster: b.clusterName,
176178
}
177179
for _, addr := range endpoint.Addresses {
178180
b.addressWeights.Set(addr, ew)
@@ -211,6 +213,7 @@ type wrrBalancer struct {
211213
mu sync.Mutex
212214
cfg *lbConfig // active config
213215
locality string
216+
clusterName string
214217
stopPicker *grpcsync.Event
215218
addressWeights *resolver.AddressMapV2[*endpointWeight]
216219
endpointToWeight *resolver.EndpointMap[*endpointWeight]
@@ -231,6 +234,11 @@ func (b *wrrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error
231234
b.mu.Lock()
232235
b.cfg = cfg
233236
b.locality = weightedtarget.LocalityFromResolverState(ccs.ResolverState)
237+
if cluster, ok := clusterimpl.GetBackendServiceFromState(ccs.ResolverState); !ok {
238+
b.logger.Infof("Backend service name not found in resolver state attributes.")
239+
} else {
240+
b.clusterName = cluster
241+
}
234242
b.updateEndpointsLocked(ccs.ResolverState.Endpoints)
235243
b.mu.Unlock()
236244

@@ -288,6 +296,7 @@ func (b *wrrBalancer) UpdateState(state balancer.State) {
288296
metricsRecorder: b.metricsRecorder,
289297
locality: b.locality,
290298
target: b.target,
299+
clusterName: b.clusterName,
291300
}
292301

293302
b.stopPicker = grpcsync.NewEvent()
@@ -420,6 +429,7 @@ type picker struct {
420429
// The following fields are immutable.
421430
target string
422431
locality string
432+
clusterName string
423433
metricsRecorder estats.MetricsRecorder
424434
}
425435

@@ -499,6 +509,7 @@ type endpointWeight struct {
499509
target string
500510
metricsRecorder estats.MetricsRecorder
501511
locality string
512+
cluster string
502513

503514
// The following fields are only accessed on calls into the LB policy, and
504515
// do not need a mutex.
@@ -602,14 +613,14 @@ func (w *endpointWeight) weight(now time.Time, weightExpirationPeriod, blackoutP
602613

603614
if recordMetrics {
604615
defer func() {
605-
endpointWeightsMetric.Record(w.metricsRecorder, weight, w.target, w.locality)
616+
endpointWeightsMetric.Record(w.metricsRecorder, weight, w.target, w.locality, w.cluster)
606617
}()
607618
}
608619

609620
// The endpoint has not received a load report (i.e. just turned READY with
610621
// no load report).
611622
if w.lastUpdated.Equal(time.Time{}) {
612-
endpointWeightNotYetUsableMetric.Record(w.metricsRecorder, 1, w.target, w.locality)
623+
endpointWeightNotYetUsableMetric.Record(w.metricsRecorder, 1, w.target, w.locality, w.cluster)
613624
return 0
614625
}
615626

@@ -618,7 +629,7 @@ func (w *endpointWeight) weight(now time.Time, weightExpirationPeriod, blackoutP
618629
// start getting data again in the future, and return 0.
619630
if now.Sub(w.lastUpdated) >= weightExpirationPeriod {
620631
if recordMetrics {
621-
endpointWeightStaleMetric.Record(w.metricsRecorder, 1, w.target, w.locality)
632+
endpointWeightStaleMetric.Record(w.metricsRecorder, 1, w.target, w.locality, w.cluster)
622633
}
623634
w.nonEmptySince = time.Time{}
624635
return 0
@@ -627,7 +638,7 @@ func (w *endpointWeight) weight(now time.Time, weightExpirationPeriod, blackoutP
627638
// If we don't have at least blackoutPeriod worth of data, return 0.
628639
if blackoutPeriod != 0 && (w.nonEmptySince.Equal(time.Time{}) || now.Sub(w.nonEmptySince) < blackoutPeriod) {
629640
if recordMetrics {
630-
endpointWeightNotYetUsableMetric.Record(w.metricsRecorder, 1, w.target, w.locality)
641+
endpointWeightNotYetUsableMetric.Record(w.metricsRecorder, 1, w.target, w.locality, w.cluster)
631642
}
632643
return 0
633644
}

balancer/weightedroundrobin/scheduler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (p *picker) newScheduler(recordMetrics bool) scheduler {
3939
}
4040
if n == 1 {
4141
if recordMetrics {
42-
rrFallbackMetric.Record(p.metricsRecorder, 1, p.target, p.locality)
42+
rrFallbackMetric.Record(p.metricsRecorder, 1, p.target, p.locality, p.clusterName)
4343
}
4444
return &rrScheduler{numSCs: 1, inc: p.inc}
4545
}
@@ -58,7 +58,7 @@ func (p *picker) newScheduler(recordMetrics bool) scheduler {
5858

5959
if numZero >= n-1 {
6060
if recordMetrics {
61-
rrFallbackMetric.Record(p.metricsRecorder, 1, p.target, p.locality)
61+
rrFallbackMetric.Record(p.metricsRecorder, 1, p.target, p.locality, p.clusterName)
6262
}
6363
return &rrScheduler{numSCs: uint32(n), inc: p.inc}
6464
}

clientconn.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ import (
3535
"google.golang.org/grpc/balancer/pickfirst"
3636
"google.golang.org/grpc/codes"
3737
"google.golang.org/grpc/connectivity"
38+
"google.golang.org/grpc/credentials"
39+
expstats "google.golang.org/grpc/experimental/stats"
3840
"google.golang.org/grpc/internal"
3941
"google.golang.org/grpc/internal/channelz"
4042
"google.golang.org/grpc/internal/grpcsync"
4143
"google.golang.org/grpc/internal/idle"
4244
iresolver "google.golang.org/grpc/internal/resolver"
4345
istats "google.golang.org/grpc/internal/stats"
4446
"google.golang.org/grpc/internal/transport"
47+
xdsinternal "google.golang.org/grpc/internal/xds"
4548
"google.golang.org/grpc/keepalive"
4649
"google.golang.org/grpc/resolver"
4750
"google.golang.org/grpc/serviceconfig"
@@ -98,6 +101,41 @@ var (
98101
errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
99102
)
100103

104+
var (
105+
disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
106+
Name: "grpc.subchannel.disconnections",
107+
Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
108+
Unit: "{disconnection}",
109+
Labels: []string{"grpc.target"},
110+
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality", "grpc.disconnect_error"},
111+
Default: false,
112+
})
113+
connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
114+
Name: "grpc.subchannel.connection_attempts_succeeded",
115+
Description: "EXPERIMENTAL. Number of successful connection attempts.",
116+
Unit: "{attempt}",
117+
Labels: []string{"grpc.target"},
118+
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality"},
119+
Default: false,
120+
})
121+
connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
122+
Name: "grpc.subchannel.connection_attempts_failed",
123+
Description: "EXPERIMENTAL. Number of failed connection attempts.",
124+
Unit: "{attempt}",
125+
Labels: []string{"grpc.target"},
126+
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality"},
127+
Default: false,
128+
})
129+
openConnectionsMetric = expstats.RegisterInt64UpDownCount(expstats.MetricDescriptor{
130+
Name: "grpc.subchannel.open_connections",
131+
Description: "EXPERIMENTAL. Number of open connections.",
132+
Unit: "{attempt}",
133+
Labels: []string{"grpc.target"},
134+
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.security_level", "grpc.lb.locality"},
135+
Default: false,
136+
})
137+
)
138+
101139
const (
102140
defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4
103141
defaultClientMaxSendMessageSize = math.MaxInt32
@@ -1223,6 +1261,18 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error)
12231261
if ac.state == s {
12241262
return
12251263
}
1264+
1265+
var locality, backendService string
1266+
if len(ac.addrs) > 0 {
1267+
labels := xdsinternal.AddressToTelemetryLabels(ac.addrs[0])
1268+
locality = labels["grpc.lb.locality"]
1269+
backendService = labels["grpc.lb.backend_service"]
1270+
}
1271+
1272+
if ac.state == connectivity.Ready || (ac.state == connectivity.Connecting && s == connectivity.Idle) {
1273+
disconnectionsMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, backendService, locality, "unknown")
1274+
openConnectionsMetric.Record(ac.cc.metricsRecorderList, -1, ac.cc.target, backendService, ac.securityLevel(), locality)
1275+
}
12261276
ac.state = s
12271277
ac.channelz.ChannelMetrics.State.Store(&s)
12281278
if lastErr == nil {
@@ -1276,10 +1326,18 @@ func (ac *addrConn) resetTransportAndUnlock() {
12761326
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md#proposed-backoff-algorithm
12771327
connectDeadline := time.Now().Add(dialDuration)
12781328

1329+
var locality, backendService string
1330+
if len(ac.addrs) > 0 {
1331+
labels := xdsinternal.AddressToTelemetryLabels(ac.addrs[0])
1332+
locality = labels["grpc.lb.locality"]
1333+
backendService = labels["grpc.lb.backend_service"]
1334+
}
1335+
12791336
ac.updateConnectivityState(connectivity.Connecting, nil)
12801337
ac.mu.Unlock()
12811338

12821339
if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil {
1340+
connectionAttemptsFailedMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, backendService, locality)
12831341
// TODO: #7534 - Move re-resolution requests into the pick_first LB policy
12841342
// to ensure one resolution request per pass instead of per subconn failure.
12851343
ac.cc.resolveNow(resolver.ResolveNowOptions{})
@@ -1319,10 +1377,30 @@ func (ac *addrConn) resetTransportAndUnlock() {
13191377
}
13201378
// Success; reset backoff.
13211379
ac.mu.Lock()
1380+
connectionAttemptsSucceededMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, backendService, locality)
1381+
openConnectionsMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, backendService, ac.securityLevel(), locality)
13221382
ac.backoffIdx = 0
13231383
ac.mu.Unlock()
13241384
}
13251385

1386+
type securityLevelKey struct{}
1387+
1388+
func (ac *addrConn) securityLevel() string {
1389+
var secLevel string
1390+
if ac.transport == nil {
1391+
secLevel, _ = ac.curAddr.Attributes.Value(securityLevelKey{}).(string)
1392+
return secLevel
1393+
}
1394+
authInfo := ac.transport.AuthInfo()
1395+
if ci, ok := authInfo.(interface {
1396+
GetCommonAuthInfo() credentials.CommonAuthInfo
1397+
}); ok {
1398+
secLevel = ci.GetCommonAuthInfo().SecurityLevel.String()
1399+
ac.curAddr.Attributes = ac.curAddr.Attributes.WithValue(securityLevelKey{}, secLevel)
1400+
}
1401+
return secLevel
1402+
}
1403+
13261404
// tryAllAddrs tries to create a connection to the addresses, and stop when at
13271405
// the first successful one. It returns an error if no address was successfully
13281406
// connected, or updates ac appropriately with the new transport.

0 commit comments

Comments
 (0)