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.namequeues;
019
020import java.util.Map;
021import org.apache.commons.lang3.builder.ToStringBuilder;
022import org.apache.hadoop.hbase.ipc.RpcCall;
023import org.apache.yetus.audience.InterfaceAudience;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026
027import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
028import org.apache.hbase.thirdparty.com.google.protobuf.Message;
029
030/**
031 * RpcCall details that would be passed on to ring buffer of slow log responses
032 */
033@InterfaceAudience.Private
034public class RpcLogDetails extends NamedQueuePayload {
035
036  public static final int SLOW_LOG_EVENT = 0;
037
038  private static final Logger LOG = LoggerFactory.getLogger(RpcLogDetails.class.getName());
039
040  private final RpcCall rpcCall;
041  private Message param;
042  private final String clientAddress;
043  private final long responseSize;
044  private final long blockBytesScanned;
045  private final long fsReadTime;
046  private final String className;
047  private final boolean isSlowLog;
048  private final boolean isLargeLog;
049  private final Map<String, byte[]> connectionAttributes;
050  private final Map<String, byte[]> requestAttributes;
051
052  public RpcLogDetails(RpcCall rpcCall, Message param, String clientAddress, long responseSize,
053    long blockBytesScanned, long fsReadTime, String className, boolean isSlowLog,
054    boolean isLargeLog) {
055    super(SLOW_LOG_EVENT);
056    this.rpcCall = rpcCall;
057    this.clientAddress = clientAddress;
058    this.responseSize = responseSize;
059    this.blockBytesScanned = blockBytesScanned;
060    this.fsReadTime = fsReadTime;
061    this.className = className;
062    this.isSlowLog = isSlowLog;
063    this.isLargeLog = isLargeLog;
064
065    // it's important to call getConnectionAttributes and getRequestAttributes here
066    // because otherwise the buffers may get released before the log details are processed which
067    // would result in corrupted attributes
068    this.connectionAttributes = rpcCall.getConnectionAttributes();
069    this.requestAttributes = rpcCall.getRequestAttributes();
070
071    // We also need to deep copy the message because the CodedInputStream may be
072    // overwritten before this slow log is consumed. Such overwriting could
073    // cause the slow log payload to be corrupt
074    try {
075      this.param = param.newBuilderForType().mergeFrom(param.toByteArray()).build();
076    } catch (InvalidProtocolBufferException e) {
077      LOG.error("Failed to parse protobuf for message {}", param, e);
078      this.param = param;
079    }
080  }
081
082  public RpcCall getRpcCall() {
083    return rpcCall;
084  }
085
086  public String getClientAddress() {
087    return clientAddress;
088  }
089
090  public long getResponseSize() {
091    return responseSize;
092  }
093
094  public long getBlockBytesScanned() {
095    return blockBytesScanned;
096  }
097
098  public long getFsReadTime() {
099    return fsReadTime;
100  }
101
102  public String getClassName() {
103    return className;
104  }
105
106  public boolean isSlowLog() {
107    return isSlowLog;
108  }
109
110  public boolean isLargeLog() {
111    return isLargeLog;
112  }
113
114  public Message getParam() {
115    return param;
116  }
117
118  public Map<String, byte[]> getConnectionAttributes() {
119    return connectionAttributes;
120  }
121
122  public Map<String, byte[]> getRequestAttributes() {
123    return requestAttributes;
124  }
125
126  @Override
127  public String toString() {
128    return new ToStringBuilder(this).append("rpcCall", rpcCall).append("param", param)
129      .append("clientAddress", clientAddress).append("responseSize", responseSize)
130      .append("className", className).append("isSlowLog", isSlowLog)
131      .append("isLargeLog", isLargeLog).append("connectionAttributes", connectionAttributes)
132      .append("requestAttributes", requestAttributes).toString();
133  }
134}