001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import java.util.Collections; 021import java.util.Map; 022import java.util.concurrent.ConcurrentHashMap; 023import java.util.concurrent.atomic.AtomicBoolean; 024import java.util.concurrent.atomic.LongAdder; 025import org.apache.hadoop.metrics2.MetricHistogram; 026import org.apache.hadoop.metrics2.MetricsCollector; 027import org.apache.hadoop.metrics2.MetricsRecordBuilder; 028import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; 029import org.apache.yetus.audience.InterfaceAudience; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033@InterfaceAudience.Private 034public class MetricsUserSourceImpl implements MetricsUserSource { 035 private static final Logger LOG = LoggerFactory.getLogger(MetricsUserSourceImpl.class); 036 037 private final String userNamePrefix; 038 039 private final String user; 040 041 private final String userGetKey; 042 private final String userScanTimeKey; 043 private final String userPutKey; 044 private final String userDeleteKey; 045 private final String userIncrementKey; 046 private final String userAppendKey; 047 private final String userReplayKey; 048 049 private MetricHistogram getHisto; 050 private MetricHistogram scanTimeHisto; 051 private MetricHistogram putHisto; 052 private MetricHistogram deleteHisto; 053 private MetricHistogram incrementHisto; 054 private MetricHistogram appendHisto; 055 private MetricHistogram replayHisto; 056 057 private final int hashCode; 058 059 private AtomicBoolean closed = new AtomicBoolean(false); 060 private final DynamicMetricsRegistry registry; 061 062 private ConcurrentHashMap<String, ClientMetrics> clientMetricsMap; 063 064 static class ClientMetricsImpl implements ClientMetrics { 065 private final String hostName; 066 final LongAdder readRequestsCount = new LongAdder(); 067 final LongAdder writeRequestsCount = new LongAdder(); 068 final LongAdder filteredRequestsCount = new LongAdder(); 069 070 public ClientMetricsImpl(String hostName) { 071 this.hostName = hostName; 072 } 073 074 @Override 075 public void incrementReadRequest() { 076 readRequestsCount.increment(); 077 } 078 079 @Override 080 public void incrementWriteRequest() { 081 writeRequestsCount.increment(); 082 } 083 084 @Override 085 public String getHostName() { 086 return hostName; 087 } 088 089 @Override 090 public long getReadRequestsCount() { 091 return readRequestsCount.sum(); 092 } 093 094 @Override 095 public long getWriteRequestsCount() { 096 return writeRequestsCount.sum(); 097 } 098 099 @Override 100 public void incrementFilteredReadRequests() { 101 filteredRequestsCount.increment(); 102 103 } 104 105 @Override 106 public long getFilteredReadRequests() { 107 return filteredRequestsCount.sum(); 108 } 109 } 110 111 public MetricsUserSourceImpl(String user, MetricsUserAggregateSourceImpl agg) { 112 if (LOG.isDebugEnabled()) { 113 LOG.debug("Creating new MetricsUserSourceImpl for user " + user); 114 } 115 116 this.user = user; 117 this.registry = agg.getMetricsRegistry(); 118 119 this.userNamePrefix = "user_" + user + "_metric_"; 120 121 hashCode = userNamePrefix.hashCode(); 122 123 userGetKey = userNamePrefix + MetricsRegionServerSource.GET_KEY; 124 userScanTimeKey = userNamePrefix + MetricsRegionServerSource.SCAN_TIME_KEY; 125 userPutKey = userNamePrefix + MetricsRegionServerSource.PUT_KEY; 126 userDeleteKey = userNamePrefix + MetricsRegionServerSource.DELETE_KEY; 127 userIncrementKey = userNamePrefix + MetricsRegionServerSource.INCREMENT_KEY; 128 userAppendKey = userNamePrefix + MetricsRegionServerSource.APPEND_KEY; 129 userReplayKey = userNamePrefix + MetricsRegionServerSource.REPLAY_KEY; 130 clientMetricsMap = new ConcurrentHashMap<>(); 131 agg.register(this); 132 } 133 134 @Override 135 public void register() { 136 synchronized (this) { 137 getHisto = registry.newTimeHistogram(userGetKey); 138 scanTimeHisto = registry.newTimeHistogram(userScanTimeKey); 139 putHisto = registry.newTimeHistogram(userPutKey); 140 deleteHisto = registry.newTimeHistogram(userDeleteKey); 141 incrementHisto = registry.newTimeHistogram(userIncrementKey); 142 appendHisto = registry.newTimeHistogram(userAppendKey); 143 replayHisto = registry.newTimeHistogram(userReplayKey); 144 } 145 } 146 147 @Override 148 public void deregister() { 149 boolean wasClosed = closed.getAndSet(true); 150 151 // Has someone else already closed this for us? 152 if (wasClosed) { 153 return; 154 } 155 156 if (LOG.isDebugEnabled()) { 157 LOG.debug("Removing user Metrics for user: " + user); 158 } 159 160 synchronized (this) { 161 registry.removeMetric(userGetKey); 162 registry.removeMetric(userScanTimeKey); 163 registry.removeMetric(userPutKey); 164 registry.removeMetric(userDeleteKey); 165 registry.removeMetric(userIncrementKey); 166 registry.removeMetric(userAppendKey); 167 registry.removeMetric(userReplayKey); 168 } 169 } 170 171 @Override 172 public String getUser() { 173 return user; 174 } 175 176 @Override 177 public int compareTo(MetricsUserSource source) { 178 if (source == null) { 179 return -1; 180 } 181 if (!(source instanceof MetricsUserSourceImpl)) { 182 return -1; 183 } 184 185 MetricsUserSourceImpl impl = (MetricsUserSourceImpl) source; 186 187 return Long.compare(hashCode, impl.hashCode); 188 } 189 190 @Override 191 public int hashCode() { 192 return hashCode; 193 } 194 195 @Override 196 public boolean equals(Object obj) { 197 return obj == this 198 || (obj instanceof MetricsUserSourceImpl && compareTo((MetricsUserSourceImpl) obj) == 0); 199 } 200 201 void snapshot(MetricsRecordBuilder mrb, boolean ignored) { 202 // If there is a close that started be double extra sure 203 // that we're not getting any locks and not putting data 204 // into the metrics that should be removed. So early out 205 // before even getting the lock. 206 if (closed.get()) { 207 return; 208 } 209 210 // Grab the read 211 // This ensures that removes of the metrics 212 // can't happen while we are putting them back in. 213 synchronized (this) { 214 215 // It's possible that a close happened between checking 216 // the closed variable and getting the lock. 217 if (closed.get()) { 218 return; 219 } 220 } 221 } 222 223 @Override 224 public void updatePut(long t) { 225 putHisto.add(t); 226 } 227 228 @Override 229 public void updateDelete(long t) { 230 deleteHisto.add(t); 231 } 232 233 @Override 234 public void updateGet(long t) { 235 getHisto.add(t); 236 } 237 238 @Override 239 public void updateIncrement(long t) { 240 incrementHisto.add(t); 241 } 242 243 @Override 244 public void updateAppend(long t) { 245 appendHisto.add(t); 246 } 247 248 @Override 249 public void updateReplay(long t) { 250 replayHisto.add(t); 251 } 252 253 @Override 254 public void updateScanTime(long t) { 255 scanTimeHisto.add(t); 256 } 257 258 @Override 259 public void getMetrics(MetricsCollector metricsCollector, boolean all) { 260 MetricsRecordBuilder mrb = metricsCollector.addRecord(this.userNamePrefix); 261 registry.snapshot(mrb, all); 262 } 263 264 @Override 265 public Map<String, ClientMetrics> getClientMetrics() { 266 return Collections.unmodifiableMap(clientMetricsMap); 267 } 268 269 @Override 270 public ClientMetrics getOrCreateMetricsClient(String client) { 271 ClientMetrics source = clientMetricsMap.get(client); 272 if (source != null) { 273 return source; 274 } 275 source = new ClientMetricsImpl(client); 276 ClientMetrics prev = clientMetricsMap.putIfAbsent(client, source); 277 if (prev != null) { 278 return prev; 279 } 280 return source; 281 } 282 283}