• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20239

14 Apr 2026 05:21PM UTC coverage: 88.809% (-0.003%) from 88.812%
#20239

push

github

web-flow
core,xds: Fix backend_service plumbing for subchannel metrics (#12735)

This PR fixes #12432.

Subchannel metrics read backend_service from EAG attributes, but xDS
currently only populates the resolution result attribute. As a result,
grpc.lb.backend_service is left unset for subchannel metrics in the cds
path.

This change adds an internal EAG-level backend_service attribute in cds
and has InternalSubchannel read that attribute for subchannel metrics,
while keeping a fallback to the existing resolution result attribute.

This PR is intentionally scoped to subchannel metrics only and does not
attempt the broader #12431 plumbing changes.

36022 of 40561 relevant lines covered (88.81%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.59
/../api/src/main/java/io/grpc/EquivalentAddressGroup.java
1
/*
2
 * Copyright 2015 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc;
18

19
import com.google.common.base.Preconditions;
20
import java.lang.annotation.Documented;
21
import java.lang.annotation.Retention;
22
import java.lang.annotation.RetentionPolicy;
23
import java.net.SocketAddress;
24
import java.util.ArrayList;
25
import java.util.Collections;
26
import java.util.List;
27

28
/**
29
 * A group of {@link SocketAddress}es that are considered equivalent when channel makes connections.
30
 *
31
 * <p>Usually the addresses are addresses resolved from the same host name, and connecting to any of
32
 * them is equally sufficient. They do have order. An address appears earlier on the list is likely
33
 * to be tried earlier.
34
 */
35
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770")
36
public final class EquivalentAddressGroup {
37

38
  /**
39
   * The authority to be used when constructing Subchannels for this EquivalentAddressGroup.
40
   * However, if the channel has overridden authority via
41
   * {@link ManagedChannelBuilder#overrideAuthority(String)}, the transport will use the channel's
42
   * authority override.
43
   *
44
   * <p>The authority <strong>must</strong> be from a trusted source, because if the authority is
45
   * tampered with, RPCs may be sent to attackers which may leak sensitive user data. If the
46
   * authority was acquired by doing I/O, the communication must be authenticated (e.g., via TLS).
47
   * Recognize that the server that provided the authority can trivially impersonate the service.
48
   */
49
  @Attr
50
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6138")
51
  public static final Attributes.Key<String> ATTR_AUTHORITY_OVERRIDE =
1✔
52
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE");
1✔
53
  /**
54
   * The name of the locality that this EquivalentAddressGroup is in.
55
   */
56
  public static final Attributes.Key<String> ATTR_LOCALITY_NAME =
1✔
57
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.LOCALITY");
1✔
58
  /**
59
   * The backend service associated with this EquivalentAddressGroup.
60
   */
61
  @Attr
62
  static final Attributes.Key<String> ATTR_BACKEND_SERVICE =
1✔
63
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.BACKEND_SERVICE");
1✔
64
  /**
65
   * Endpoint weight for load balancing purposes. While the type is Long, it must be a valid uint32.
66
   * Must not be zero. The weight is proportional to the other endpoints; if an endpoint's weight is
67
   * twice that of another endpoint, it is intended to receive twice the load.
68
   */
69
  @Attr
70
  static final Attributes.Key<Long> ATTR_WEIGHT =
1✔
71
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.ATTR_WEIGHT");
1✔
72

73
  private final List<SocketAddress> addrs;
74
  private final Attributes attrs;
75

76
  /**
77
   * {@link SocketAddress} docs say that the addresses are immutable, so we cache the hashCode.
78
   */
79
  private final int hashCode;
80

81
  /**
82
   * List constructor without {@link Attributes}.
83
   */
84
  public EquivalentAddressGroup(List<SocketAddress> addrs) {
85
    this(addrs, Attributes.EMPTY);
1✔
86
  }
1✔
87

88
  /**
89
   * List constructor with {@link Attributes}.
90
   */
91
  public EquivalentAddressGroup(List<SocketAddress> addrs, @Attr Attributes attrs) {
1✔
92
    Preconditions.checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
93
    this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
94
    this.attrs = Preconditions.checkNotNull(attrs, "attrs");
1✔
95
    // Attributes may contain mutable objects, which means Attributes' hashCode may change over
96
    // time, thus we don't cache Attributes' hashCode.
97
    hashCode = this.addrs.hashCode();
1✔
98
  }
1✔
99

100
  /**
101
   * Singleton constructor without Attributes.
102
   */
103
  public EquivalentAddressGroup(SocketAddress addr) {
104
    this(addr, Attributes.EMPTY);
1✔
105
  }
1✔
106

107
  /**
108
   * Singleton constructor with Attributes.
109
   */
110
  public EquivalentAddressGroup(SocketAddress addr, @Attr Attributes attrs) {
111
    this(Collections.singletonList(addr), attrs);
1✔
112
  }
1✔
113

114
  /**
115
   * Returns an immutable list of the addresses.
116
   */
117
  public List<SocketAddress> getAddresses() {
118
    return addrs;
1✔
119
  }
120

121
  /**
122
   * Returns the attributes.
123
   */
124
  @Attr
125
  public Attributes getAttributes() {
126
    return attrs;
1✔
127
  }
128

129
  @Override
130
  public String toString() {
131
    // EquivalentAddressGroup is intended to contain a small number of addresses for the same
132
    // endpoint(e.g., IPv4/IPv6). Aggregating many groups into a single EquivalentAddressGroup
133
    // is no longer done, so this no longer needs summarization.
134
    return "[" + addrs + "/" + attrs + "]";
1✔
135
  }
136

137
  @Override
138
  public int hashCode() {
139
    // Avoids creating an iterator on the underlying array list.
140
    return hashCode;
1✔
141
  }
142

143
  /**
144
   * Returns true if the given object is also an {@link EquivalentAddressGroup} with an equal
145
   * address list and equal attribute values.
146
   *
147
   * <p>Note that if the attributes include mutable values, it is possible for two objects to be
148
   * considered equal at one point in time and not equal at another (due to concurrent mutation of
149
   * attribute values).
150
   */
151
  @Override
152
  public boolean equals(Object other) {
153
    if (this == other) {
1✔
154
      return true;
1✔
155
    }
156
    if (!(other instanceof EquivalentAddressGroup)) {
1✔
157
      return false;
×
158
    }
159
    EquivalentAddressGroup that = (EquivalentAddressGroup) other;
1✔
160
    if (addrs.size() != that.addrs.size()) {
1✔
161
      return false;
×
162
    }
163
    // Avoids creating an iterator on the underlying array list.
164
    for (int i = 0; i < addrs.size(); i++) {
1✔
165
      if (!addrs.get(i).equals(that.addrs.get(i))) {
1✔
166
        return false;
1✔
167
      }
168
    }
169
    if (!attrs.equals(that.attrs)) {
1✔
170
      return false;
1✔
171
    }
172
    return true;
1✔
173
  }
174

175
  /**
176
   * Annotation for {@link EquivalentAddressGroup}'s attributes. It follows the annotation semantics
177
   * defined by {@link Attributes}.
178
   */
179
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4972")
180
  @Retention(RetentionPolicy.SOURCE)
181
  @Documented
182
  public @interface Attr {}
183
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc