4141import io .grpc .util .ForwardingSubchannel ;
4242import io .grpc .util .MultiChildLoadBalancer ;
4343import io .grpc .xds .internal .MetricReportUtils ;
44+ import io .grpc .xds .internal .MetricReportUtils .ParsedMetricName ;
4445import io .grpc .xds .orca .OrcaOobUtil ;
4546import io .grpc .xds .orca .OrcaOobUtil .OrcaOobReportListener ;
4647import io .grpc .xds .orca .OrcaPerRequestUtil ;
@@ -239,7 +240,7 @@ protected void updateOverallBalancingState() {
239240 private SubchannelPicker createReadyPicker (Collection <ChildLbState > activeList ) {
240241 WeightedRoundRobinPicker picker = new WeightedRoundRobinPicker (ImmutableList .copyOf (activeList ),
241242 config .enableOobLoadReport , config .errorUtilizationPenalty , sequence ,
242- config .metricNamesForComputingUtilization );
243+ config .parsedMetricNamesForComputingUtilization );
243244 updateWeight (picker );
244245 return picker ;
245246 }
@@ -329,15 +330,15 @@ public void addSubchannel(WrrSubchannel wrrSubchannel) {
329330 }
330331
331332 public OrcaReportListener getOrCreateOrcaListener (float errorUtilizationPenalty ,
332- ImmutableList <String > metricNamesForComputingUtilization ) {
333+ ImmutableList <ParsedMetricName > parsedMetricNamesForComputingUtilization ) {
333334 if (orcaReportListener != null
334335 && orcaReportListener .errorUtilizationPenalty == errorUtilizationPenalty
335- && orcaReportListener .metricNamesForComputingUtilization
336- .equals (metricNamesForComputingUtilization )) {
336+ && orcaReportListener .parsedMetricNamesForComputingUtilization
337+ .equals (parsedMetricNamesForComputingUtilization )) {
337338 return orcaReportListener ;
338339 }
339340 orcaReportListener =
340- new OrcaReportListener (errorUtilizationPenalty , metricNamesForComputingUtilization );
341+ new OrcaReportListener (errorUtilizationPenalty , parsedMetricNamesForComputingUtilization );
341342 return orcaReportListener ;
342343 }
343344
@@ -362,17 +363,17 @@ public void updateBalancingState(ConnectivityState newState, SubchannelPicker ne
362363
363364 final class OrcaReportListener implements OrcaPerRequestReportListener , OrcaOobReportListener {
364365 private final float errorUtilizationPenalty ;
365- private final ImmutableList <String > metricNamesForComputingUtilization ;
366+ private final ImmutableList <ParsedMetricName > parsedMetricNamesForComputingUtilization ;
366367
367368 OrcaReportListener (float errorUtilizationPenalty ,
368- ImmutableList <String > metricNamesForComputingUtilization ) {
369+ ImmutableList <ParsedMetricName > parsedMetricNamesForComputingUtilization ) {
369370 this .errorUtilizationPenalty = errorUtilizationPenalty ;
370- this .metricNamesForComputingUtilization = metricNamesForComputingUtilization ;
371+ this .parsedMetricNamesForComputingUtilization = parsedMetricNamesForComputingUtilization ;
371372 }
372373
373374 @ Override
374375 public void onLoadReport (MetricReport report ) {
375- double utilization = getUtilization (report , metricNamesForComputingUtilization );
376+ double utilization = getUtilization (report );
376377
377378 double newWeight = 0 ;
378379 if (utilization > 0 && report .getQps () > 0 ) {
@@ -398,8 +399,8 @@ public void onLoadReport(MetricReport report) {
398399 * if application utilization is > 0, it is returned. If neither are present, the CPU
399400 * utilization is returned.
400401 */
401- private double getUtilization (MetricReport report , ImmutableList < String > metricNames ) {
402- OptionalDouble customUtil = getCustomMetricUtilization (report , metricNames );
402+ private double getUtilization (MetricReport report ) {
403+ OptionalDouble customUtil = getCustomMetricUtilization (report );
403404 if (customUtil .isPresent ()) {
404405 return customUtil .getAsDouble ();
405406 }
@@ -411,19 +412,23 @@ private double getUtilization(MetricReport report, ImmutableList<String> metricN
411412 }
412413
413414 /**
414- * Returns the maximum utilization value among the specified metric names.
415+ * Returns the maximum utilization value among the parsed metric names.
415416 * Returns OptionalDouble.empty() if NONE of the specified metrics are present in the report,
416- * or if all present metrics are NaN.
417- * Returns OptionalDouble.of(maxUtil) if at least one non-NaN metric is present.
417+ * or if all present metrics are NaN or non positive.
418418 */
419- private OptionalDouble getCustomMetricUtilization (MetricReport report ,
420- ImmutableList <String > metricNames ) {
421- return metricNames .stream ()
422- .map (name -> MetricReportUtils .getMetric (report , name ))
423- .filter (OptionalDouble ::isPresent )
424- .mapToDouble (OptionalDouble ::getAsDouble )
425- .filter (d -> !Double .isNaN (d ) && d > 0 )
426- .max ();
419+ private OptionalDouble getCustomMetricUtilization (MetricReport report ) {
420+ OptionalDouble max = OptionalDouble .empty ();
421+ for (int i = 0 ; i < parsedMetricNamesForComputingUtilization .size (); i ++) {
422+ OptionalDouble opt = MetricReportUtils .getMetricValue (report ,
423+ parsedMetricNamesForComputingUtilization .get (i ));
424+ if (opt .isPresent ()) {
425+ double d = opt .getAsDouble ();
426+ if (!Double .isNaN (d ) && d > 0 && (!max .isPresent () || d > max .getAsDouble ())) {
427+ max = opt ;
428+ }
429+ }
430+ }
431+ return max ;
427432 }
428433 }
429434 }
@@ -446,7 +451,7 @@ private void createAndApplyOrcaListeners() {
446451 if (config .enableOobLoadReport ) {
447452 OrcaOobUtil .setListener (weightedSubchannel ,
448453 wChild .getOrCreateOrcaListener (config .errorUtilizationPenalty ,
449- config .metricNamesForComputingUtilization ),
454+ config .parsedMetricNamesForComputingUtilization ),
450455 OrcaOobUtil .OrcaReportingConfig .newBuilder ()
451456 .setReportInterval (config .oobReportingPeriodNanos , TimeUnit .NANOSECONDS ).build ());
452457 } else {
@@ -516,7 +521,7 @@ static final class WeightedRoundRobinPicker extends SubchannelPicker {
516521
517522 WeightedRoundRobinPicker (List <ChildLbState > children , boolean enableOobLoadReport ,
518523 float errorUtilizationPenalty , AtomicInteger sequence ,
519- ImmutableList <String > metricNamesForComputingUtilization ) {
524+ ImmutableList <ParsedMetricName > parsedMetricNamesForComputingUtilization ) {
520525 checkNotNull (children , "children" );
521526 Preconditions .checkArgument (!children .isEmpty (), "empty child list" );
522527 this .children = children ;
@@ -526,7 +531,7 @@ static final class WeightedRoundRobinPicker extends SubchannelPicker {
526531 WeightedChildLbState wChild = (WeightedChildLbState ) child ;
527532 pickers .add (wChild .getCurrentPicker ());
528533 reportListeners .add (wChild .getOrCreateOrcaListener (errorUtilizationPenalty ,
529- metricNamesForComputingUtilization ));
534+ parsedMetricNamesForComputingUtilization ));
530535 }
531536 this .pickers = pickers ;
532537 this .reportListeners = reportListeners ;
@@ -767,7 +772,7 @@ static final class WeightedRoundRobinLoadBalancerConfig {
767772 final long oobReportingPeriodNanos ;
768773 final long weightUpdatePeriodNanos ;
769774 final float errorUtilizationPenalty ;
770- final ImmutableList <String > metricNamesForComputingUtilization ;
775+ final ImmutableList <ParsedMetricName > parsedMetricNamesForComputingUtilization ;
771776
772777 public static Builder newBuilder () {
773778 return new Builder ();
@@ -783,7 +788,20 @@ private WeightedRoundRobinLoadBalancerConfig(long blackoutPeriodNanos,
783788 this .oobReportingPeriodNanos = oobReportingPeriodNanos ;
784789 this .weightUpdatePeriodNanos = weightUpdatePeriodNanos ;
785790 this .errorUtilizationPenalty = errorUtilizationPenalty ;
786- this .metricNamesForComputingUtilization = metricNamesForComputingUtilization ;
791+
792+ ImmutableList .Builder <ParsedMetricName > builder = ImmutableList .builder ();
793+ if (metricNamesForComputingUtilization != null ) {
794+ for (int i = 0 ; i < metricNamesForComputingUtilization .size (); i ++) {
795+ String metricName = metricNamesForComputingUtilization .get (i );
796+ ParsedMetricName parsed = MetricReportUtils .ParsedMetricName .parse (metricName );
797+ if (parsed .getMetricType () != MetricReportUtils .MetricType .INVALID ) {
798+ builder .add (parsed );
799+ } else {
800+ log .log (Level .FINE , "Invalid custom metric name configured and ignored: " + metricName );
801+ }
802+ }
803+ }
804+ this .parsedMetricNamesForComputingUtilization = builder .build ();
787805 }
788806
789807 @ Override
@@ -799,15 +817,15 @@ public boolean equals(Object o) {
799817 && this .weightUpdatePeriodNanos == that .weightUpdatePeriodNanos
800818 // Float.compare considers NaNs equal
801819 && Float .compare (this .errorUtilizationPenalty , that .errorUtilizationPenalty ) == 0
802- && Objects .equals (this .metricNamesForComputingUtilization ,
803- that .metricNamesForComputingUtilization );
820+ && Objects .equals (this .parsedMetricNamesForComputingUtilization ,
821+ that .parsedMetricNamesForComputingUtilization );
804822 }
805823
806824 @ Override
807825 public int hashCode () {
808826 return Objects .hash (blackoutPeriodNanos , weightExpirationPeriodNanos , enableOobLoadReport ,
809827 oobReportingPeriodNanos , weightUpdatePeriodNanos , errorUtilizationPenalty ,
810- metricNamesForComputingUtilization );
828+ parsedMetricNamesForComputingUtilization );
811829 }
812830
813831 static final class Builder {
0 commit comments