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.client; 019 020import java.util.Map; 021import java.util.Optional; 022import org.apache.commons.lang3.builder.EqualsBuilder; 023import org.apache.commons.lang3.builder.HashCodeBuilder; 024import org.apache.commons.lang3.builder.ToStringBuilder; 025import org.apache.hadoop.hbase.util.GsonUtil; 026import org.apache.yetus.audience.InterfaceAudience; 027import org.apache.yetus.audience.InterfaceStability; 028 029import org.apache.hbase.thirdparty.com.google.gson.Gson; 030import org.apache.hbase.thirdparty.com.google.gson.JsonObject; 031import org.apache.hbase.thirdparty.com.google.gson.JsonSerializer; 032 033import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 034 035/** 036 * Slow/Large Log payload for hbase-client, to be used by Admin API get_slow_responses and 037 * get_large_responses 038 */ 039@InterfaceAudience.Public 040@InterfaceStability.Evolving 041final public class OnlineLogRecord extends LogEntry { 042 043 // used to convert object to pretty printed format 044 // used by toJsonPrettyPrint() 045 private static final Gson GSON = 046 GsonUtil.createGson().setPrettyPrinting().registerTypeAdapter(OnlineLogRecord.class, 047 (JsonSerializer<OnlineLogRecord>) (slowLogPayload, type, jsonSerializationContext) -> { 048 Gson gson = new Gson(); 049 JsonObject jsonObj = (JsonObject) gson.toJsonTree(slowLogPayload); 050 if (slowLogPayload.getMultiGetsCount() == 0) { 051 jsonObj.remove("multiGetsCount"); 052 } 053 if (slowLogPayload.getMultiMutationsCount() == 0) { 054 jsonObj.remove("multiMutationsCount"); 055 } 056 if (slowLogPayload.getMultiServiceCalls() == 0) { 057 jsonObj.remove("multiServiceCalls"); 058 } 059 if (slowLogPayload.getRequestAttributes().isEmpty()) { 060 jsonObj.remove("requestAttributes"); 061 } else { 062 jsonObj.add("requestAttributes", gson 063 .toJsonTree(ProtobufUtil.deserializeAttributes(slowLogPayload.getRequestAttributes()))); 064 } 065 if (slowLogPayload.getConnectionAttributes().isEmpty()) { 066 jsonObj.remove("connectionAttributes"); 067 } else { 068 jsonObj.add("connectionAttributes", gson.toJsonTree( 069 ProtobufUtil.deserializeAttributes(slowLogPayload.getConnectionAttributes()))); 070 } 071 if (slowLogPayload.getScan().isPresent()) { 072 jsonObj.add("scan", gson.toJsonTree(slowLogPayload.getScan().get().toMap())); 073 } else { 074 jsonObj.remove("scan"); 075 } 076 return jsonObj; 077 }).create(); 078 079 private final long startTime; 080 private final int processingTime; 081 private final int queueTime; 082 private final long responseSize; 083 private final long blockBytesScanned; 084 private final long fsReadTime; 085 private final String clientAddress; 086 private final String serverClass; 087 private final String methodName; 088 private final String callDetails; 089 private final String param; 090 // we don't want to serialize region name, it is just for the filter purpose 091 // hence avoiding deserialization 092 private final transient String regionName; 093 private final String userName; 094 private final int multiGetsCount; 095 private final int multiMutationsCount; 096 private final int multiServiceCalls; 097 private final Optional<Scan> scan; 098 private final Map<String, byte[]> requestAttributes; 099 private final Map<String, byte[]> connectionAttributes; 100 101 public long getStartTime() { 102 return startTime; 103 } 104 105 public int getProcessingTime() { 106 return processingTime; 107 } 108 109 public int getQueueTime() { 110 return queueTime; 111 } 112 113 public long getResponseSize() { 114 return responseSize; 115 } 116 117 /** 118 * Return the amount of block bytes scanned to retrieve the response cells. 119 */ 120 public long getBlockBytesScanned() { 121 return blockBytesScanned; 122 } 123 124 public long getFsReadTime() { 125 return fsReadTime; 126 } 127 128 public String getClientAddress() { 129 return clientAddress; 130 } 131 132 public String getServerClass() { 133 return serverClass; 134 } 135 136 public String getMethodName() { 137 return methodName; 138 } 139 140 public String getCallDetails() { 141 return callDetails; 142 } 143 144 public String getParam() { 145 return param; 146 } 147 148 public String getRegionName() { 149 return regionName; 150 } 151 152 public String getUserName() { 153 return userName; 154 } 155 156 public int getMultiGetsCount() { 157 return multiGetsCount; 158 } 159 160 public int getMultiMutationsCount() { 161 return multiMutationsCount; 162 } 163 164 public int getMultiServiceCalls() { 165 return multiServiceCalls; 166 } 167 168 /** 169 * If {@value org.apache.hadoop.hbase.HConstants#SLOW_LOG_SCAN_PAYLOAD_ENABLED} is enabled then 170 * this value may be present and should represent the Scan that produced the given 171 * {@link OnlineLogRecord} 172 */ 173 public Optional<Scan> getScan() { 174 return scan; 175 } 176 177 public Map<String, byte[]> getRequestAttributes() { 178 return requestAttributes; 179 } 180 181 public Map<String, byte[]> getConnectionAttributes() { 182 return connectionAttributes; 183 } 184 185 OnlineLogRecord(final long startTime, final int processingTime, final int queueTime, 186 final long responseSize, final long blockBytesScanned, final long fsReadTime, 187 final String clientAddress, final String serverClass, final String methodName, 188 final String callDetails, final String param, final String regionName, final String userName, 189 final int multiGetsCount, final int multiMutationsCount, final int multiServiceCalls, 190 final Scan scan, final Map<String, byte[]> requestAttributes, 191 final Map<String, byte[]> connectionAttributes) { 192 this.startTime = startTime; 193 this.processingTime = processingTime; 194 this.queueTime = queueTime; 195 this.responseSize = responseSize; 196 this.blockBytesScanned = blockBytesScanned; 197 this.fsReadTime = fsReadTime; 198 this.clientAddress = clientAddress; 199 this.serverClass = serverClass; 200 this.methodName = methodName; 201 this.callDetails = callDetails; 202 this.param = param; 203 this.regionName = regionName; 204 this.userName = userName; 205 this.multiGetsCount = multiGetsCount; 206 this.multiMutationsCount = multiMutationsCount; 207 this.multiServiceCalls = multiServiceCalls; 208 this.scan = Optional.ofNullable(scan); 209 this.requestAttributes = requestAttributes; 210 this.connectionAttributes = connectionAttributes; 211 } 212 213 public static class OnlineLogRecordBuilder { 214 private long startTime; 215 private int processingTime; 216 private int queueTime; 217 private long responseSize; 218 private long blockBytesScanned; 219 private long fsReadTime; 220 private String clientAddress; 221 private String serverClass; 222 private String methodName; 223 private String callDetails; 224 private String param; 225 private String regionName; 226 private String userName; 227 private int multiGetsCount; 228 private int multiMutationsCount; 229 private int multiServiceCalls; 230 private Scan scan = null; 231 private Map<String, byte[]> requestAttributes; 232 private Map<String, byte[]> connectionAttributes; 233 234 public OnlineLogRecordBuilder setStartTime(long startTime) { 235 this.startTime = startTime; 236 return this; 237 } 238 239 public OnlineLogRecordBuilder setProcessingTime(int processingTime) { 240 this.processingTime = processingTime; 241 return this; 242 } 243 244 public OnlineLogRecordBuilder setQueueTime(int queueTime) { 245 this.queueTime = queueTime; 246 return this; 247 } 248 249 public OnlineLogRecordBuilder setResponseSize(long responseSize) { 250 this.responseSize = responseSize; 251 return this; 252 } 253 254 /** 255 * Sets the amount of block bytes scanned to retrieve the response cells. 256 */ 257 public OnlineLogRecordBuilder setBlockBytesScanned(long blockBytesScanned) { 258 this.blockBytesScanned = blockBytesScanned; 259 return this; 260 } 261 262 public OnlineLogRecordBuilder setFsReadTime(long fsReadTime) { 263 this.fsReadTime = fsReadTime; 264 return this; 265 } 266 267 public OnlineLogRecordBuilder setClientAddress(String clientAddress) { 268 this.clientAddress = clientAddress; 269 return this; 270 } 271 272 public OnlineLogRecordBuilder setServerClass(String serverClass) { 273 this.serverClass = serverClass; 274 return this; 275 } 276 277 public OnlineLogRecordBuilder setMethodName(String methodName) { 278 this.methodName = methodName; 279 return this; 280 } 281 282 public OnlineLogRecordBuilder setCallDetails(String callDetails) { 283 this.callDetails = callDetails; 284 return this; 285 } 286 287 public OnlineLogRecordBuilder setParam(String param) { 288 this.param = param; 289 return this; 290 } 291 292 public OnlineLogRecordBuilder setRegionName(String regionName) { 293 this.regionName = regionName; 294 return this; 295 } 296 297 public OnlineLogRecordBuilder setUserName(String userName) { 298 this.userName = userName; 299 return this; 300 } 301 302 public OnlineLogRecordBuilder setMultiGetsCount(int multiGetsCount) { 303 this.multiGetsCount = multiGetsCount; 304 return this; 305 } 306 307 public OnlineLogRecordBuilder setMultiMutationsCount(int multiMutationsCount) { 308 this.multiMutationsCount = multiMutationsCount; 309 return this; 310 } 311 312 public OnlineLogRecordBuilder setMultiServiceCalls(int multiServiceCalls) { 313 this.multiServiceCalls = multiServiceCalls; 314 return this; 315 } 316 317 public OnlineLogRecordBuilder setScan(Scan scan) { 318 this.scan = scan; 319 return this; 320 } 321 322 public OnlineLogRecordBuilder setRequestAttributes(Map<String, byte[]> requestAttributes) { 323 this.requestAttributes = requestAttributes; 324 return this; 325 } 326 327 public OnlineLogRecordBuilder 328 setConnectionAttributes(Map<String, byte[]> connectionAttributes) { 329 this.connectionAttributes = connectionAttributes; 330 return this; 331 } 332 333 public OnlineLogRecord build() { 334 return new OnlineLogRecord(startTime, processingTime, queueTime, responseSize, 335 blockBytesScanned, fsReadTime, clientAddress, serverClass, methodName, callDetails, param, 336 regionName, userName, multiGetsCount, multiMutationsCount, multiServiceCalls, scan, 337 requestAttributes, connectionAttributes); 338 } 339 } 340 341 @Override 342 public boolean equals(Object o) { 343 if (this == o) { 344 return true; 345 } 346 347 if (o == null || getClass() != o.getClass()) { 348 return false; 349 } 350 351 OnlineLogRecord that = (OnlineLogRecord) o; 352 353 return new EqualsBuilder().append(startTime, that.startTime) 354 .append(processingTime, that.processingTime).append(queueTime, that.queueTime) 355 .append(responseSize, that.responseSize).append(blockBytesScanned, that.blockBytesScanned) 356 .append(multiGetsCount, that.multiGetsCount) 357 .append(multiMutationsCount, that.multiMutationsCount) 358 .append(multiServiceCalls, that.multiServiceCalls).append(clientAddress, that.clientAddress) 359 .append(serverClass, that.serverClass).append(methodName, that.methodName) 360 .append(callDetails, that.callDetails).append(param, that.param) 361 .append(regionName, that.regionName).append(userName, that.userName).append(scan, that.scan) 362 .append(requestAttributes, that.requestAttributes) 363 .append(connectionAttributes, that.connectionAttributes).isEquals(); 364 } 365 366 @Override 367 public int hashCode() { 368 return new HashCodeBuilder(17, 37).append(startTime).append(processingTime).append(queueTime) 369 .append(responseSize).append(blockBytesScanned).append(clientAddress).append(serverClass) 370 .append(methodName).append(callDetails).append(param).append(regionName).append(userName) 371 .append(multiGetsCount).append(multiMutationsCount).append(multiServiceCalls).append(scan) 372 .append(requestAttributes).append(connectionAttributes).toHashCode(); 373 } 374 375 @Override 376 public String toJsonPrettyPrint() { 377 return GSON.toJson(this); 378 } 379 380 @Override 381 public String toString() { 382 return new ToStringBuilder(this).append("startTime", startTime) 383 .append("processingTime", processingTime).append("queueTime", queueTime) 384 .append("responseSize", responseSize).append("blockBytesScanned", blockBytesScanned) 385 .append("clientAddress", clientAddress).append("serverClass", serverClass) 386 .append("methodName", methodName).append("callDetails", callDetails).append("param", param) 387 .append("regionName", regionName).append("userName", userName) 388 .append("multiGetsCount", multiGetsCount).append("multiMutationsCount", multiMutationsCount) 389 .append("multiServiceCalls", multiServiceCalls).append("scan", scan) 390 .append("requestAttributes", requestAttributes) 391 .append("connectionAttributes", connectionAttributes).toString(); 392 } 393 394}