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 String clientAddress; 085 private final String serverClass; 086 private final String methodName; 087 private final String callDetails; 088 private final String param; 089 // we don't want to serialize region name, it is just for the filter purpose 090 // hence avoiding deserialization 091 private final transient String regionName; 092 private final String userName; 093 private final int multiGetsCount; 094 private final int multiMutationsCount; 095 private final int multiServiceCalls; 096 private final Optional<Scan> scan; 097 private final Map<String, byte[]> requestAttributes; 098 private final Map<String, byte[]> connectionAttributes; 099 100 public long getStartTime() { 101 return startTime; 102 } 103 104 public int getProcessingTime() { 105 return processingTime; 106 } 107 108 public int getQueueTime() { 109 return queueTime; 110 } 111 112 public long getResponseSize() { 113 return responseSize; 114 } 115 116 /** 117 * Return the amount of block bytes scanned to retrieve the response cells. 118 */ 119 public long getBlockBytesScanned() { 120 return blockBytesScanned; 121 } 122 123 public String getClientAddress() { 124 return clientAddress; 125 } 126 127 public String getServerClass() { 128 return serverClass; 129 } 130 131 public String getMethodName() { 132 return methodName; 133 } 134 135 public String getCallDetails() { 136 return callDetails; 137 } 138 139 public String getParam() { 140 return param; 141 } 142 143 public String getRegionName() { 144 return regionName; 145 } 146 147 public String getUserName() { 148 return userName; 149 } 150 151 public int getMultiGetsCount() { 152 return multiGetsCount; 153 } 154 155 public int getMultiMutationsCount() { 156 return multiMutationsCount; 157 } 158 159 public int getMultiServiceCalls() { 160 return multiServiceCalls; 161 } 162 163 /** 164 * If {@value org.apache.hadoop.hbase.HConstants#SLOW_LOG_SCAN_PAYLOAD_ENABLED} is enabled then 165 * this value may be present and should represent the Scan that produced the given 166 * {@link OnlineLogRecord} 167 */ 168 public Optional<Scan> getScan() { 169 return scan; 170 } 171 172 public Map<String, byte[]> getRequestAttributes() { 173 return requestAttributes; 174 } 175 176 public Map<String, byte[]> getConnectionAttributes() { 177 return connectionAttributes; 178 } 179 180 OnlineLogRecord(final long startTime, final int processingTime, final int queueTime, 181 final long responseSize, final long blockBytesScanned, final String clientAddress, 182 final String serverClass, final String methodName, final String callDetails, final String param, 183 final String regionName, final String userName, final int multiGetsCount, 184 final int multiMutationsCount, final int multiServiceCalls, final Scan scan, 185 final Map<String, byte[]> requestAttributes, final Map<String, byte[]> connectionAttributes) { 186 this.startTime = startTime; 187 this.processingTime = processingTime; 188 this.queueTime = queueTime; 189 this.responseSize = responseSize; 190 this.blockBytesScanned = blockBytesScanned; 191 this.clientAddress = clientAddress; 192 this.serverClass = serverClass; 193 this.methodName = methodName; 194 this.callDetails = callDetails; 195 this.param = param; 196 this.regionName = regionName; 197 this.userName = userName; 198 this.multiGetsCount = multiGetsCount; 199 this.multiMutationsCount = multiMutationsCount; 200 this.multiServiceCalls = multiServiceCalls; 201 this.scan = Optional.ofNullable(scan); 202 this.requestAttributes = requestAttributes; 203 this.connectionAttributes = connectionAttributes; 204 } 205 206 public static class OnlineLogRecordBuilder { 207 private long startTime; 208 private int processingTime; 209 private int queueTime; 210 private long responseSize; 211 private long blockBytesScanned; 212 private String clientAddress; 213 private String serverClass; 214 private String methodName; 215 private String callDetails; 216 private String param; 217 private String regionName; 218 private String userName; 219 private int multiGetsCount; 220 private int multiMutationsCount; 221 private int multiServiceCalls; 222 private Scan scan = null; 223 private Map<String, byte[]> requestAttributes; 224 private Map<String, byte[]> connectionAttributes; 225 226 public OnlineLogRecordBuilder setStartTime(long startTime) { 227 this.startTime = startTime; 228 return this; 229 } 230 231 public OnlineLogRecordBuilder setProcessingTime(int processingTime) { 232 this.processingTime = processingTime; 233 return this; 234 } 235 236 public OnlineLogRecordBuilder setQueueTime(int queueTime) { 237 this.queueTime = queueTime; 238 return this; 239 } 240 241 public OnlineLogRecordBuilder setResponseSize(long responseSize) { 242 this.responseSize = responseSize; 243 return this; 244 } 245 246 /** 247 * Sets the amount of block bytes scanned to retrieve the response cells. 248 */ 249 public OnlineLogRecordBuilder setBlockBytesScanned(long blockBytesScanned) { 250 this.blockBytesScanned = blockBytesScanned; 251 return this; 252 } 253 254 public OnlineLogRecordBuilder setClientAddress(String clientAddress) { 255 this.clientAddress = clientAddress; 256 return this; 257 } 258 259 public OnlineLogRecordBuilder setServerClass(String serverClass) { 260 this.serverClass = serverClass; 261 return this; 262 } 263 264 public OnlineLogRecordBuilder setMethodName(String methodName) { 265 this.methodName = methodName; 266 return this; 267 } 268 269 public OnlineLogRecordBuilder setCallDetails(String callDetails) { 270 this.callDetails = callDetails; 271 return this; 272 } 273 274 public OnlineLogRecordBuilder setParam(String param) { 275 this.param = param; 276 return this; 277 } 278 279 public OnlineLogRecordBuilder setRegionName(String regionName) { 280 this.regionName = regionName; 281 return this; 282 } 283 284 public OnlineLogRecordBuilder setUserName(String userName) { 285 this.userName = userName; 286 return this; 287 } 288 289 public OnlineLogRecordBuilder setMultiGetsCount(int multiGetsCount) { 290 this.multiGetsCount = multiGetsCount; 291 return this; 292 } 293 294 public OnlineLogRecordBuilder setMultiMutationsCount(int multiMutationsCount) { 295 this.multiMutationsCount = multiMutationsCount; 296 return this; 297 } 298 299 public OnlineLogRecordBuilder setMultiServiceCalls(int multiServiceCalls) { 300 this.multiServiceCalls = multiServiceCalls; 301 return this; 302 } 303 304 public OnlineLogRecordBuilder setScan(Scan scan) { 305 this.scan = scan; 306 return this; 307 } 308 309 public OnlineLogRecordBuilder setRequestAttributes(Map<String, byte[]> requestAttributes) { 310 this.requestAttributes = requestAttributes; 311 return this; 312 } 313 314 public OnlineLogRecordBuilder 315 setConnectionAttributes(Map<String, byte[]> connectionAttributes) { 316 this.connectionAttributes = connectionAttributes; 317 return this; 318 } 319 320 public OnlineLogRecord build() { 321 return new OnlineLogRecord(startTime, processingTime, queueTime, responseSize, 322 blockBytesScanned, clientAddress, serverClass, methodName, callDetails, param, regionName, 323 userName, multiGetsCount, multiMutationsCount, multiServiceCalls, scan, requestAttributes, 324 connectionAttributes); 325 } 326 } 327 328 @Override 329 public boolean equals(Object o) { 330 if (this == o) { 331 return true; 332 } 333 334 if (o == null || getClass() != o.getClass()) { 335 return false; 336 } 337 338 OnlineLogRecord that = (OnlineLogRecord) o; 339 340 return new EqualsBuilder().append(startTime, that.startTime) 341 .append(processingTime, that.processingTime).append(queueTime, that.queueTime) 342 .append(responseSize, that.responseSize).append(blockBytesScanned, that.blockBytesScanned) 343 .append(multiGetsCount, that.multiGetsCount) 344 .append(multiMutationsCount, that.multiMutationsCount) 345 .append(multiServiceCalls, that.multiServiceCalls).append(clientAddress, that.clientAddress) 346 .append(serverClass, that.serverClass).append(methodName, that.methodName) 347 .append(callDetails, that.callDetails).append(param, that.param) 348 .append(regionName, that.regionName).append(userName, that.userName).append(scan, that.scan) 349 .append(requestAttributes, that.requestAttributes) 350 .append(connectionAttributes, that.connectionAttributes).isEquals(); 351 } 352 353 @Override 354 public int hashCode() { 355 return new HashCodeBuilder(17, 37).append(startTime).append(processingTime).append(queueTime) 356 .append(responseSize).append(blockBytesScanned).append(clientAddress).append(serverClass) 357 .append(methodName).append(callDetails).append(param).append(regionName).append(userName) 358 .append(multiGetsCount).append(multiMutationsCount).append(multiServiceCalls).append(scan) 359 .append(requestAttributes).append(connectionAttributes).toHashCode(); 360 } 361 362 @Override 363 public String toJsonPrettyPrint() { 364 return GSON.toJson(this); 365 } 366 367 @Override 368 public String toString() { 369 return new ToStringBuilder(this).append("startTime", startTime) 370 .append("processingTime", processingTime).append("queueTime", queueTime) 371 .append("responseSize", responseSize).append("blockBytesScanned", blockBytesScanned) 372 .append("clientAddress", clientAddress).append("serverClass", serverClass) 373 .append("methodName", methodName).append("callDetails", callDetails).append("param", param) 374 .append("regionName", regionName).append("userName", userName) 375 .append("multiGetsCount", multiGetsCount).append("multiMutationsCount", multiMutationsCount) 376 .append("multiServiceCalls", multiServiceCalls).append("scan", scan) 377 .append("requestAttributes", requestAttributes) 378 .append("connectionAttributes", connectionAttributes).toString(); 379 } 380 381}