HBASE-11344 Hide row keys and such from the web UIs
This commit is contained in:
parent
15831cefd5
commit
9f8d1876a0
|
@ -261,4 +261,13 @@
|
|||
<Bug pattern="FE_FLOATING_POINT_EQUALITY"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="org.apache.hadoop.hbase.HRegionInfo"/>
|
||||
<Or>
|
||||
<Method name="getEndKeyForDisplay"/>
|
||||
<Method name="getStartKeyForDisplay"/>
|
||||
</Or>
|
||||
<Bug pattern="MS_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
</FindBugsFilter>
|
||||
|
|
|
@ -33,9 +33,11 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.KeyValue.KVComparator;
|
||||
import org.apache.hadoop.hbase.client.Result;
|
||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||
import org.apache.hadoop.hbase.master.RegionState;
|
||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
|
||||
|
@ -220,6 +222,9 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
|
|||
|
||||
// Current TableName
|
||||
private TableName tableName = null;
|
||||
final static String DISPLAY_KEYS_KEY = "hbase.display.keys";
|
||||
public final static byte[] HIDDEN_END_KEY = Bytes.toBytes("hidden-end-key");
|
||||
public final static byte[] HIDDEN_START_KEY = Bytes.toBytes("hidden-start-key");
|
||||
|
||||
/** HRegionInfo for first meta region */
|
||||
public static final HRegionInfo FIRST_META_REGIONINFO =
|
||||
|
@ -1122,6 +1127,104 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
|
|||
return ProtobufUtil.toDelimitedByteArray(convert());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the descriptive name as {@link RegionState} does it but with hidden
|
||||
* startkey optionally
|
||||
* @param state
|
||||
* @param conf
|
||||
* @return descriptive string
|
||||
*/
|
||||
public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
|
||||
Configuration conf) {
|
||||
if (conf.getBoolean(DISPLAY_KEYS_KEY, true)) return state.toDescriptiveString();
|
||||
String descriptiveStringFromState = state.toDescriptiveString();
|
||||
int idx = descriptiveStringFromState.lastIndexOf(" state=");
|
||||
String regionName = getRegionNameAsStringForDisplay(state.getRegion(), conf);
|
||||
return regionName + descriptiveStringFromState.substring(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end key for display. Optionally hide the real end key.
|
||||
* @param hri
|
||||
* @param conf
|
||||
* @return the endkey
|
||||
*/
|
||||
public static byte[] getEndKeyForDisplay(HRegionInfo hri, Configuration conf) {
|
||||
boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
|
||||
if (displayKey) return hri.getEndKey();
|
||||
return HIDDEN_END_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start key for display. Optionally hide the real start key.
|
||||
* @param hri
|
||||
* @param conf
|
||||
* @return the startkey
|
||||
*/
|
||||
public static byte[] getStartKeyForDisplay(HRegionInfo hri, Configuration conf) {
|
||||
boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
|
||||
if (displayKey) return hri.getStartKey();
|
||||
return HIDDEN_START_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the region name for display. Optionally hide the start key.
|
||||
* @param hri
|
||||
* @param conf
|
||||
* @return region name as String
|
||||
*/
|
||||
public static String getRegionNameAsStringForDisplay(HRegionInfo hri, Configuration conf) {
|
||||
return Bytes.toStringBinary(getRegionNameForDisplay(hri, conf));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the region name for display. Optionally hide the start key.
|
||||
* @param hri
|
||||
* @param conf
|
||||
* @return region name bytes
|
||||
*/
|
||||
public static byte[] getRegionNameForDisplay(HRegionInfo hri, Configuration conf) {
|
||||
boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
|
||||
if (displayKey || hri.getTable().equals(TableName.META_TABLE_NAME)) {
|
||||
return hri.getRegionName();
|
||||
} else {
|
||||
// create a modified regionname with the startkey replaced but preserving
|
||||
// the other parts including the encodedname.
|
||||
try {
|
||||
byte[][]regionNameParts = parseRegionName(hri.getRegionName());
|
||||
regionNameParts[1] = HIDDEN_START_KEY; //replace the real startkey
|
||||
int len = 0;
|
||||
// get the total length
|
||||
for (byte[] b : regionNameParts) {
|
||||
len += b.length;
|
||||
}
|
||||
byte[] encodedRegionName =
|
||||
Bytes.toBytes(encodeRegionName(hri.getRegionName()));
|
||||
len += encodedRegionName.length;
|
||||
//allocate some extra bytes for the delimiters and the last '.'
|
||||
byte[] modifiedName = new byte[len + regionNameParts.length + 1];
|
||||
int lengthSoFar = 0;
|
||||
int loopCount = 0;
|
||||
for (byte[] b : regionNameParts) {
|
||||
System.arraycopy(b, 0, modifiedName, lengthSoFar, b.length);
|
||||
lengthSoFar += b.length;
|
||||
if (loopCount++ == 2) modifiedName[lengthSoFar++] = REPLICA_ID_DELIMITER;
|
||||
else modifiedName[lengthSoFar++] = HConstants.DELIMITER;
|
||||
}
|
||||
// replace the last comma with '.'
|
||||
modifiedName[lengthSoFar - 1] = ENC_SEPARATOR;
|
||||
System.arraycopy(encodedRegionName, 0, modifiedName, lengthSoFar,
|
||||
encodedRegionName.length);
|
||||
lengthSoFar += encodedRegionName.length;
|
||||
modifiedName[lengthSoFar] = ENC_SEPARATOR;
|
||||
return modifiedName;
|
||||
} catch (IOException e) {
|
||||
//LOG.warn("Encountered exception " + e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a HRegionInfo and ServerName from catalog table {@link Result}.
|
||||
* @param r Result to pull from
|
||||
|
|
|
@ -836,6 +836,13 @@ possible configurations would overwhelm and obscure the important.
|
|||
When false (the default), the client will not allow the fallback to SIMPLE
|
||||
authentication, and will abort the connection.</description>
|
||||
</property>
|
||||
<property>
|
||||
<name>hbase.display.keys</name>
|
||||
<value>true</value>
|
||||
<description>When this is set to true the webUI and such will display all start/end keys
|
||||
as part of the table details, region names, etc. When this is set to false,
|
||||
the keys are hidden.</description>
|
||||
</property>
|
||||
<property>
|
||||
<name>hbase.coprocessor.region.classes</name>
|
||||
<value></value>
|
||||
|
|
|
@ -85,7 +85,9 @@ if (toRemove > 0) {
|
|||
<%else>
|
||||
<tr>
|
||||
</%if>
|
||||
<td><% entry.getKey() %></td><td><% entry.getValue().toDescriptiveString() %></td>
|
||||
<td><% entry.getKey() %></td><td>
|
||||
<% HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(
|
||||
entry.getValue(), conf) %></td>
|
||||
<td><% (currentTime - entry.getValue().getStamp()) %> </td></tr>
|
||||
</%for>
|
||||
<tr BGCOLOR="#D7DF01"> <td>Total number of Regions in Transition for more than <% ritThreshold %> milliseconds</td><td> <% numOfRITOverThreshold %></td><td></td>
|
||||
|
|
|
@ -93,9 +93,12 @@
|
|||
|
||||
<%for HRegionInfo r: onlineRegions %>
|
||||
<tr>
|
||||
<td><% r.getRegionNameAsString() %></td>
|
||||
<td><% Bytes.toStringBinary(r.getStartKey()) %></td>
|
||||
<td><% Bytes.toStringBinary(r.getEndKey()) %></td>
|
||||
<td><% HRegionInfo.getRegionNameAsStringForDisplay(r,
|
||||
regionServer.getConfiguration()) %></td>
|
||||
<td><% Bytes.toStringBinary(HRegionInfo.getStartKeyForDisplay(r,
|
||||
regionServer.getConfiguration())) %></td>
|
||||
<td><% Bytes.toStringBinary(HRegionInfo.getEndKeyForDisplay(r,
|
||||
regionServer.getConfiguration())) %></td>
|
||||
<td><% r.getReplicaId() %></td>
|
||||
</tr>
|
||||
</%for>
|
||||
|
@ -119,7 +122,8 @@
|
|||
<%java>
|
||||
RegionLoad load = regionServer.createRegionLoad(r.getEncodedName());
|
||||
</%java>
|
||||
<td><% r.getRegionNameAsString() %></td>
|
||||
<td><% HRegionInfo.getRegionNameAsStringForDisplay(r,
|
||||
regionServer.getConfiguration()) %></td>
|
||||
<%if load != null %>
|
||||
<td><% load.getReadRequestsCount() %></td>
|
||||
<td><% load.getWriteRequestsCount() %></td>
|
||||
|
@ -151,7 +155,8 @@
|
|||
<%java>
|
||||
RegionLoad load = regionServer.createRegionLoad(r.getEncodedName());
|
||||
</%java>
|
||||
<td><% r.getRegionNameAsString() %></td>
|
||||
<td><% HRegionInfo.getRegionNameAsStringForDisplay(r,
|
||||
regionServer.getConfiguration()) %></td>
|
||||
<%if load != null %>
|
||||
<td><% load.getStores() %></td>
|
||||
<td><% load.getStorefiles() %></td>
|
||||
|
@ -189,7 +194,8 @@
|
|||
((float) load.getCurrentCompactedKVs() / load.getTotalCompactingKVs())) + "%";
|
||||
}
|
||||
</%java>
|
||||
<td><% r.getRegionNameAsString() %></td>
|
||||
<td><% HRegionInfo.getRegionNameAsStringForDisplay(r,
|
||||
regionServer.getConfiguration()) %></td>
|
||||
<%if load != null %>
|
||||
<td><% load.getTotalCompactingKVs() %></td>
|
||||
<td><% load.getCurrentCompactedKVs() %></td>
|
||||
|
@ -216,7 +222,8 @@
|
|||
<%java>
|
||||
RegionLoad load = regionServer.createRegionLoad(r.getEncodedName());
|
||||
</%java>
|
||||
<td><% r.getRegionNameAsString() %></td>
|
||||
<td><% HRegionInfo.getRegionNameAsStringForDisplay(r,
|
||||
regionServer.getConfiguration()) %></td>
|
||||
<%if load != null %>
|
||||
<td><% load.getMemstoreSizeMB() %>m</td>
|
||||
</%if>
|
||||
|
|
|
@ -283,7 +283,8 @@
|
|||
}
|
||||
%>
|
||||
<tr>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getRegionNameForDisplay(regionInfo,
|
||||
conf))) %></td>
|
||||
<%
|
||||
if (addr != null) {
|
||||
String url = "//" + addr.getHostname() + ":" + master.getRegionServerInfoPort(addr) + "/";
|
||||
|
@ -298,8 +299,10 @@
|
|||
<%
|
||||
}
|
||||
%>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(regionInfo.getStartKey())) %></td>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(regionInfo.getEndKey())) %></td>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getStartKeyForDisplay(regionInfo,
|
||||
conf))) %></td>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getEndKeyForDisplay(regionInfo,
|
||||
conf))) %></td>
|
||||
<td><%= req%></td>
|
||||
<%
|
||||
if (withReplica) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.FileStatus;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||
|
@ -34,10 +35,12 @@ import org.apache.hadoop.hbase.HTableDescriptor;
|
|||
import org.apache.hadoop.hbase.SmallTests;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||
import org.apache.hadoop.hbase.master.RegionState;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.util.MD5Hash;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
|
@ -254,6 +257,71 @@ public class TestHRegionInfo {
|
|||
|
||||
assertEquals(expectedHri, convertedHri);
|
||||
}
|
||||
@Test
|
||||
public void testRegionDetailsForDisplay() throws IOException {
|
||||
byte[] startKey = new byte[] {0x01, 0x01, 0x02, 0x03};
|
||||
byte[] endKey = new byte[] {0x01, 0x01, 0x02, 0x04};
|
||||
Configuration conf = new Configuration();
|
||||
conf.setBoolean("hbase.display.keys", false);
|
||||
HRegionInfo h = new HRegionInfo(TableName.valueOf("foo"), startKey, endKey);
|
||||
checkEquality(h, conf);
|
||||
// check HRIs with non-default replicaId
|
||||
h = new HRegionInfo(TableName.valueOf("foo"), startKey, endKey, false,
|
||||
System.currentTimeMillis(), 1);
|
||||
checkEquality(h, conf);
|
||||
Assert.assertArrayEquals(HRegionInfo.HIDDEN_END_KEY,
|
||||
HRegionInfo.getEndKeyForDisplay(h, conf));
|
||||
Assert.assertArrayEquals(HRegionInfo.HIDDEN_START_KEY,
|
||||
HRegionInfo.getStartKeyForDisplay(h, conf));
|
||||
|
||||
RegionState state = new RegionState(h, RegionState.State.OPEN);
|
||||
String descriptiveNameForDisplay =
|
||||
HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(state, conf);
|
||||
checkDescriptiveNameEquality(descriptiveNameForDisplay,state.toDescriptiveString(), startKey);
|
||||
|
||||
conf.setBoolean("hbase.display.keys", true);
|
||||
Assert.assertArrayEquals(endKey, HRegionInfo.getEndKeyForDisplay(h, conf));
|
||||
Assert.assertArrayEquals(startKey, HRegionInfo.getStartKeyForDisplay(h, conf));
|
||||
Assert.assertEquals(state.toDescriptiveString(),
|
||||
HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(state, conf));
|
||||
}
|
||||
|
||||
private void checkDescriptiveNameEquality(String descriptiveNameForDisplay, String origDesc,
|
||||
byte[] startKey) {
|
||||
// except for the "hidden-start-key" substring everything else should exactly match
|
||||
String firstPart = descriptiveNameForDisplay.substring(0,
|
||||
descriptiveNameForDisplay.indexOf(new String(HRegionInfo.HIDDEN_START_KEY)));
|
||||
String secondPart = descriptiveNameForDisplay.substring(
|
||||
descriptiveNameForDisplay.indexOf(new String(HRegionInfo.HIDDEN_START_KEY)) +
|
||||
HRegionInfo.HIDDEN_START_KEY.length);
|
||||
String firstPartOrig = origDesc.substring(0,
|
||||
origDesc.indexOf(Bytes.toStringBinary(startKey)));
|
||||
String secondPartOrig = origDesc.substring(
|
||||
origDesc.indexOf(Bytes.toStringBinary(startKey)) +
|
||||
Bytes.toStringBinary(startKey).length());
|
||||
assert(firstPart.equals(firstPartOrig));
|
||||
assert(secondPart.equals(secondPartOrig));
|
||||
}
|
||||
|
||||
private void checkEquality(HRegionInfo h, Configuration conf) throws IOException {
|
||||
byte[] modifiedRegionName = HRegionInfo.getRegionNameForDisplay(h, conf);
|
||||
byte[][] modifiedRegionNameParts = HRegionInfo.parseRegionName(modifiedRegionName);
|
||||
byte[][] regionNameParts = HRegionInfo.parseRegionName(h.getRegionName());
|
||||
|
||||
//same number of parts
|
||||
assert(modifiedRegionNameParts.length == regionNameParts.length);
|
||||
|
||||
for (int i = 0; i < regionNameParts.length; i++) {
|
||||
// all parts should match except for [1] where in the modified one,
|
||||
// we should have "hidden_start_key"
|
||||
if (i != 1) {
|
||||
Assert.assertArrayEquals(regionNameParts[i], modifiedRegionNameParts[i]);
|
||||
} else {
|
||||
Assert.assertNotEquals(regionNameParts[i][0], modifiedRegionNameParts[i][0]);
|
||||
Assert.assertArrayEquals(modifiedRegionNameParts[1],
|
||||
HRegionInfo.getStartKeyForDisplay(h, conf));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue