This is an automated email from the ASF dual-hosted git repository.
nickallen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/metron.git
The following commit(s) were added to refs/heads/master by this push:
new 9641aec METRON-1985 Improve Error Handling When Cannot Connect to
HBase (nickwallen) closes apache/metron#1327
9641aec is described below
commit 9641aec6284102d16db2fbfd1dc5960d6767008a
Author: nickwallen <[email protected]>
AuthorDate: Tue Feb 12 12:30:36 2019 -0500
METRON-1985 Improve Error Handling When Cannot Connect to HBase
(nickwallen) closes apache/metron#1327
---
.../apache/metron/hbase/client/HBaseClient.java | 40 ++++++++++++---
.../metron/hbase/client/HBaseClientTest.java | 57 ++++++++++++++++++++--
2 files changed, 87 insertions(+), 10 deletions(-)
diff --git
a/metron-platform/metron-hbase/src/main/java/org/apache/metron/hbase/client/HBaseClient.java
b/metron-platform/metron-hbase/src/main/java/org/apache/metron/hbase/client/HBaseClient.java
index f0a0a10..c416f47 100644
---
a/metron-platform/metron-hbase/src/main/java/org/apache/metron/hbase/client/HBaseClient.java
+++
b/metron-platform/metron-hbase/src/main/java/org/apache/metron/hbase/client/HBaseClient.java
@@ -25,6 +25,8 @@ import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
+
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Durability;
import org.apache.hadoop.hbase.client.Get;
@@ -39,6 +41,8 @@ import
org.apache.metron.hbase.bolt.mapper.HBaseProjectionCriteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.commons.collections4.CollectionUtils.size;
+
/**
* A client that interacts with HBase.
*/
@@ -67,7 +71,9 @@ public class HBaseClient implements Closeable {
try {
this.table = provider.getTable(configuration, tableName);
} catch (Exception e) {
- throw new RuntimeException(e);
+ String msg = String.format("Unable to open connection to HBase for table
'%s'", tableName);
+ LOG.error(msg, e);
+ throw new RuntimeException(msg, e);
}
}
@@ -142,9 +148,10 @@ public class HBaseClient implements Closeable {
table.batch(mutations, result);
mutations.clear();
- } catch (InterruptedException | IOException e) {
- LOG.warn("Error performing a mutation to HBase.", e);
- throw new RuntimeException(e);
+ } catch (Exception e) {
+ String msg = String.format("'%d' HBase write(s) failed on table '%s'",
size(mutations), tableName(table));
+ LOG.error(msg, e);
+ throw new RuntimeException(msg, e);
}
return mutationCount;
@@ -187,8 +194,9 @@ public class HBaseClient implements Closeable {
return results;
} catch (Exception e) {
- LOG.warn("Could not perform HBase lookup.", e);
- throw new RuntimeException(e);
+ String msg = String.format("'%d' HBase read(s) failed on table '%s'",
size(gets), tableName(table));
+ LOG.error(msg, e);
+ throw new RuntimeException(msg, e);
}
}
@@ -197,7 +205,9 @@ public class HBaseClient implements Closeable {
*/
@Override
public void close() throws IOException {
- table.close();
+ if(table != null) {
+ table.close();
+ }
}
/**
@@ -276,4 +286,20 @@ public class HBaseClient implements Closeable {
cols.getCounters().forEach(cnt -> inc.addColumn(cnt.getFamily(),
cnt.getQualifier(), cnt.getIncrement()));
return inc;
}
+
+ /**
+ * Returns the name of the HBase table.
+ * <p>Attempts to avoid any null pointers that might be encountered along
the way.
+ * @param table The table to retrieve the name of.
+ * @return The name of the table
+ */
+ private static String tableName(HTableInterface table) {
+ String tableName = "null";
+ if(table != null) {
+ if(table.getName() != null) {
+ tableName = table.getName().getNameAsString();
+ }
+ }
+ return tableName;
+ }
}
diff --git
a/metron-platform/metron-hbase/src/test/java/org/apache/metron/hbase/client/HBaseClientTest.java
b/metron-platform/metron-hbase/src/test/java/org/apache/metron/hbase/client/HBaseClientTest.java
index ca1f5a6..e6247d0 100644
---
a/metron-platform/metron-hbase/src/test/java/org/apache/metron/hbase/client/HBaseClientTest.java
+++
b/metron-platform/metron-hbase/src/test/java/org/apache/metron/hbase/client/HBaseClientTest.java
@@ -20,18 +20,24 @@
package org.apache.metron.hbase.client;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.*;
-import org.apache.storm.tuple.Tuple;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.client.Admin;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Durability;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.metron.hbase.TableProvider;
import org.apache.metron.hbase.Widget;
import org.apache.metron.hbase.WidgetMapper;
import org.apache.metron.hbase.bolt.mapper.ColumnList;
import org.apache.metron.hbase.bolt.mapper.HBaseMapper;
import org.apache.metron.hbase.bolt.mapper.HBaseProjectionCriteria;
+import org.apache.storm.tuple.Tuple;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
@@ -39,6 +45,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -49,6 +56,9 @@ import static org.apache.metron.hbase.WidgetMapper.CF;
import static org.apache.metron.hbase.WidgetMapper.QCOST;
import static org.apache.metron.hbase.WidgetMapper.QNAME;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -268,6 +278,47 @@ public class HBaseClientTest {
assertEquals(0, widgets.size());
}
+ @Test(expected = RuntimeException.class)
+ public void testUnableToOpenConnection() throws IOException {
+ // used to trigger a failure condition
+ TableProvider tableProvider = mock(TableProvider.class);
+ when(tableProvider.getTable(any(), any())).thenThrow(new
IllegalArgumentException("test exception"));
+
+ client = new HBaseClient(tableProvider, HBaseConfiguration.create(),
tableName);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testFailureToMutate() throws IOException, InterruptedException {
+ // used to trigger a failure condition in `HbaseClient.mutate`
+ HTableInterface table = mock(HTableInterface.class);
+ doThrow(new IOException("exception!")).when(table).batch(any(), any());
+
+ TableProvider tableProvider = mock(TableProvider.class);
+ when(tableProvider.getTable(any(), any())).thenReturn(table);
+
+ client = new HBaseClient(tableProvider, HBaseConfiguration.create(),
tableName);
+ client.addMutation(rowKey1, cols1, Durability.SYNC_WAL);
+ client.mutate();
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testFailureToGetAll() throws IOException {
+ // used to trigger a failure condition in `HbaseClient.getAll`
+ HTableInterface table = mock(HTableInterface.class);
+ when(table.get(anyListOf(Get.class))).thenThrow(new
IOException("exception!"));
+
+ TableProvider tableProvider = mock(TableProvider.class);
+ when(tableProvider.getTable(any(), any())).thenReturn(table);
+
+ HBaseProjectionCriteria criteria = new HBaseProjectionCriteria();
+ criteria.addColumnFamily(WidgetMapper.CF_STRING);
+
+ client = new HBaseClient(tableProvider, HBaseConfiguration.create(),
tableName);
+ client.addGet(rowKey1, criteria);
+ client.addGet(rowKey2, criteria);
+ client.getAll();
+ }
+
/**
* Transforms the HBase Result to a Widget.
* @param result The HBase Result.