1 /* 2 * Copyright 2022 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.services; 18 19 import io.grpc.ExperimentalApi; 20 import java.util.Collections; 21 import java.util.Map; 22 import java.util.concurrent.ConcurrentHashMap; 23 24 /** 25 * Implements the service/APIs for Out-of-Band metrics reporting, only for utilization metrics. 26 * A user should use the public set-APIs to update the server machine's utilization metrics data. 27 */ 28 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/9006") 29 public final class MetricRecorder { 30 private volatile ConcurrentHashMap<String, Double> metricsData = new ConcurrentHashMap<>(); 31 private volatile double cpuUtilization; 32 private volatile double applicationUtilization; 33 private volatile double memoryUtilization; 34 private volatile double qps; 35 private volatile double eps; 36 newInstance()37 public static MetricRecorder newInstance() { 38 return new MetricRecorder(); 39 } 40 MetricRecorder()41 private MetricRecorder() {} 42 43 /** 44 * Update the metrics value in the range [0, 1] corresponding to the specified key. Values outside 45 * the valid range are ignored. 46 */ putUtilizationMetric(String key, double value)47 public void putUtilizationMetric(String key, double value) { 48 if (!MetricRecorderHelper.isUtilizationValid(value)) { 49 return; 50 } 51 metricsData.put(key, value); 52 } 53 54 /** 55 * Replace the whole metrics data using the specified map. No range validation. 56 */ setAllUtilizationMetrics(Map<String, Double> metrics)57 public void setAllUtilizationMetrics(Map<String, Double> metrics) { 58 metricsData = new ConcurrentHashMap<>(metrics); 59 } 60 61 /** 62 * Remove the metrics data entry corresponding to the specified key. 63 */ removeUtilizationMetric(String key)64 public void removeUtilizationMetric(String key) { 65 metricsData.remove(key); 66 } 67 68 /** 69 * Update the CPU utilization metrics data in the range [0, inf). Values outside the valid range 70 * are ignored. 71 */ setCpuUtilizationMetric(double value)72 public void setCpuUtilizationMetric(double value) { 73 if (!MetricRecorderHelper.isCpuOrApplicationUtilizationValid(value)) { 74 return; 75 } 76 cpuUtilization = value; 77 } 78 79 /** 80 * Clear the CPU utilization metrics data. 81 */ clearCpuUtilizationMetric()82 public void clearCpuUtilizationMetric() { 83 cpuUtilization = 0; 84 } 85 86 /** 87 * Update the application specific utilization metrics data in the range [0, inf). Values outside 88 * the valid range are ignored. 89 */ setApplicationUtilizationMetric(double value)90 public void setApplicationUtilizationMetric(double value) { 91 if (!MetricRecorderHelper.isCpuOrApplicationUtilizationValid(value)) { 92 return; 93 } 94 applicationUtilization = value; 95 } 96 97 /** 98 * Clear the application specific utilization metrics data. 99 */ clearApplicationUtilizationMetric()100 public void clearApplicationUtilizationMetric() { 101 applicationUtilization = 0; 102 } 103 104 /** 105 * Update the memory utilization metrics data in the range [0, 1]. Values outside the valid range 106 * are ignored. 107 */ setMemoryUtilizationMetric(double value)108 public void setMemoryUtilizationMetric(double value) { 109 if (!MetricRecorderHelper.isUtilizationValid(value)) { 110 return; 111 } 112 memoryUtilization = value; 113 } 114 115 /** 116 * Clear the memory utilization metrics data. 117 */ clearMemoryUtilizationMetric()118 public void clearMemoryUtilizationMetric() { 119 memoryUtilization = 0; 120 } 121 122 /** 123 * Update the QPS metrics data in the range [0, inf). Values outside the valid range are ignored. 124 */ setQpsMetric(double value)125 public void setQpsMetric(double value) { 126 if (!MetricRecorderHelper.isRateValid(value)) { 127 return; 128 } 129 qps = value; 130 } 131 132 /** 133 * Clear the QPS metrics data. 134 */ clearQpsMetric()135 public void clearQpsMetric() { 136 qps = 0; 137 } 138 139 /** 140 * Update the EPS metrics data in the range [0, inf). Values outside the valid range are ignored. 141 */ setEpsMetric(double value)142 public void setEpsMetric(double value) { 143 if (!MetricRecorderHelper.isRateValid(value)) { 144 return; 145 } 146 this.eps = value; 147 } 148 149 /** 150 * Clear the EPS metrics data. 151 */ clearEpsMetric()152 public void clearEpsMetric() { 153 eps = 0; 154 } 155 getMetricReport()156 MetricReport getMetricReport() { 157 return new MetricReport(cpuUtilization, applicationUtilization, memoryUtilization, qps, eps, 158 Collections.emptyMap(), Collections.unmodifiableMap(metricsData)); 159 } 160 } 161