From a137e44e6797fd7826266a2919d543fabc7d1d76 Mon Sep 17 00:00:00 2001 From: Rahul Date: Mon, 27 Feb 2017 14:55:41 -0800 Subject: [PATCH 1/2] added initial checkin --- .../org/apache/phoenix/query/QueryServices.java | 5 ++++- .../apache/phoenix/query/QueryServicesOptions.java | 13 +++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java index 8f0b06ec5af..e97b3066943 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java @@ -243,7 +243,10 @@ public interface QueryServices extends SQLCloseable { public static final String DEFAULT_COLUMN_ENCODED_BYTES_ATRRIB = "phoenix.default.column.encoded.bytes.attrib"; public static final String DEFAULT_IMMUTABLE_STORAGE_SCHEME_ATTRIB = "phoenix.default.immutable.storage.scheme"; public static final String DEFAULT_MULTITENANT_IMMUTABLE_STORAGE_SCHEME_ATTRIB = "phoenix.default.multitenant.immutable.storage.scheme"; - + public static final String PHOENIX_QUERY_SERVER_METRICS = "phoenix.query.server.metrics"; + public static final String PHOENIX_PQS_GLOBAL_INITIAL_DELAY="phoenix.pqs.global.metrics" + + ".initial.delay.seconds"; + public static final String PHOENIX_PQS_GLOBAL_PERIOD="phoenix.pqs.global.metrics.period.seconds"; /** * Get executor service used for parallel scans */ diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java index 15ea956d178..c993c9aeb0c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java @@ -82,6 +82,9 @@ import static org.apache.phoenix.query.QueryServices.UPLOAD_BINARY_DATA_TYPE_ENCODING; import static org.apache.phoenix.query.QueryServices.USE_BYTE_BASED_REGEX_ATTRIB; import static org.apache.phoenix.query.QueryServices.USE_INDEXES_ATTRIB; +import static org.apache.phoenix.query.QueryServices.PHOENIX_PQS_GLOBAL_INITIAL_DELAY; +import static org.apache.phoenix.query.QueryServices.PHOENIX_QUERY_SERVER_METRICS; +import static org.apache.phoenix.query.QueryServices.PHOENIX_PQS_GLOBAL_PERIOD; import java.util.HashSet; import java.util.Map.Entry; @@ -286,7 +289,10 @@ public class QueryServicesOptions { // 4.10, psql and CSVBulkLoad // expects binary data to be base 64 // encoded - + public static final boolean DEFAULT_PHOENIX_QUERY_SERVER_METRICS = false; + public static final int DEFAULT_PHOENIX_PQS_GLOBAL_INITIAL_DELAY = 5; + public static final int DEFAULT_PHOENIX_PQS_GLOBAL_PERIOD = 10; + private final Configuration config; private QueryServicesOptions(Configuration config) { @@ -354,7 +360,10 @@ public static QueryServicesOptions withDefaults() { .setIfUnset(IS_SYSTEM_TABLE_MAPPED_TO_NAMESPACE, DEFAULT_IS_SYSTEM_TABLE_MAPPED_TO_NAMESPACE) .setIfUnset(LOCAL_INDEX_CLIENT_UPGRADE_ATTRIB, DEFAULT_LOCAL_INDEX_CLIENT_UPGRADE) .setIfUnset(AUTO_UPGRADE_ENABLED, DEFAULT_AUTO_UPGRADE_ENABLED) - .setIfUnset(UPLOAD_BINARY_DATA_TYPE_ENCODING, DEFAULT_UPLOAD_BINARY_DATA_TYPE_ENCODING); + .setIfUnset(UPLOAD_BINARY_DATA_TYPE_ENCODING, DEFAULT_UPLOAD_BINARY_DATA_TYPE_ENCODING) + .setIfUnset(PHOENIX_QUERY_SERVER_METRICS,DEFAULT_PHOENIX_QUERY_SERVER_METRICS) + .setIfUnset(PHOENIX_PQS_GLOBAL_INITIAL_DELAY,DEFAULT_PHOENIX_PQS_GLOBAL_INITIAL_DELAY) + .setIfUnset(PHOENIX_PQS_GLOBAL_PERIOD,DEFAULT_PHOENIX_PQS_GLOBAL_PERIOD); // HBase sets this to 1, so we reset it to something more appropriate. // Hopefully HBase will change this, because we can't know if a user set // it to 1, so we'll change it. From f9b3a40e0832e9da2f405bf20bfaf2d14f598c04 Mon Sep 17 00:00:00 2001 From: Rahul Date: Mon, 27 Feb 2017 14:16:36 -0800 Subject: [PATCH 2/2] Initial structure for metrics collection Signed-off-by: Rahul --- .../phoenix/jdbc/PhoenixConnectionPQS.java | 98 +++++++++++++++++++ .../phoenix/jdbc/PhoenixStatementPQS.java | 53 ++++++++++ .../monitoring/PhoenixQueryServerSink.java | 41 ++++++++ .../query/ConnectionQueryServicesImpl.java | 10 +- .../metrics/MetricsBindingModule.java | 39 ++++++++ .../metrics/PhoenixQueryServerFileSink.java | 68 +++++++++++++ .../PhoenixQueryServerGlobalMetrics.java | 61 ++++++++++++ .../queryserver/server/QueryServer.java | 15 ++- 8 files changed, 382 insertions(+), 3 deletions(-) create mode 100644 phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnectionPQS.java create mode 100644 phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatementPQS.java create mode 100644 phoenix-core/src/main/java/org/apache/phoenix/monitoring/PhoenixQueryServerSink.java create mode 100644 phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/MetricsBindingModule.java create mode 100644 phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerFileSink.java create mode 100644 phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerGlobalMetrics.java diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnectionPQS.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnectionPQS.java new file mode 100644 index 00000000000..b3e6a32e766 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnectionPQS.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.jdbc; + +import com.google.inject.Inject; +import com.google.inject.servlet.RequestScoped; +import org.apache.commons.codec.language.bm.Rule; +import org.apache.phoenix.execute.MutationState; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; +import org.apache.phoenix.query.ConnectionQueryServices; +import org.apache.phoenix.schema.PMetaData; +import org.apache.phoenix.util.PhoenixRuntime; + + +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * + * Implementation of commit and close methods for PQS. + * Currently the following are supported: + * + * + * @since + */ +public class PhoenixConnectionPQS extends PhoenixConnection { + + @Inject + private PhoenixQueryServerSink phoenixQueryServerSink; + + public PhoenixConnectionPQS(PhoenixConnection connection, boolean isDescRowKeyOrderUpgrade, boolean isRunningUpgrade) throws SQLException { + super(connection, isDescRowKeyOrderUpgrade, isRunningUpgrade); + } + + public PhoenixConnectionPQS(PhoenixConnection connection) throws SQLException { + super(connection); + } + + public PhoenixConnectionPQS(PhoenixConnection connection, MutationState mutationState) throws SQLException { + super(connection, mutationState); + } + + public PhoenixConnectionPQS(PhoenixConnection connection, long scn) throws SQLException { + super(connection, scn); + } + + public PhoenixConnectionPQS(ConnectionQueryServices services, PhoenixConnection connection, long scn) throws SQLException { + super(services, connection, scn); + } + + public PhoenixConnectionPQS(ConnectionQueryServices services, String url, Properties info, PMetaData metaData) throws SQLException { + super(services, url, info, metaData); + } + + public PhoenixConnectionPQS(PhoenixConnection connection, ConnectionQueryServices services, Properties info) throws SQLException { + super(connection, services, info); + } + + public PhoenixConnectionPQS(ConnectionQueryServices services, String url, Properties info, PMetaData metaData, MutationState mutationState, boolean isDescVarLengthRowKeyUpgrade, boolean isRunningUpgrade) throws SQLException { + super(services, url, info, metaData, mutationState, isDescVarLengthRowKeyUpgrade, isRunningUpgrade); + } + + @Override + public void commit() throws SQLException { + super.commit(); + phoenixQueryServerSink.putMetrics(PhoenixRuntime.getWriteMetricsForMutationsSinceLastReset(this)); + phoenixQueryServerSink.putMetrics(PhoenixRuntime.getReadMetricsForMutationsSinceLastReset(this)); + PhoenixRuntime.resetMetrics(this); + } + + + @Override + public Statement createStatement() throws SQLException { + Statement statement=super.createStatement(new PhoenixStatementFactory() { + @Override + public PhoenixStatement newStatement(PhoenixConnection connection) { + return new PhoenixStatementPQS(connection); + } + }); + return statement; + } +} diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatementPQS.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatementPQS.java new file mode 100644 index 00000000000..7efcd900147 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatementPQS.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.jdbc; + +import com.google.inject.Inject; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; +import org.apache.phoenix.util.PhoenixRuntime; + +import java.sql.SQLException; + + +/** + * + * JDBC statement but with extra functionality of generating + * phoenix metrics after statement is closed. + * + * + * @since 0.1 + */ +public class PhoenixStatementPQS extends PhoenixStatement { + + @Inject + private PhoenixQueryServerSink phoenixQueryServerSink; + + public PhoenixStatementPQS(PhoenixConnection connection) { + super(connection); + } + + @Override + public void close() throws SQLException { + super.close(); + phoenixQueryServerSink.putMetricsOverall(PhoenixRuntime.getOverAllReadRequestMetrics(this.getResultSet())); + phoenixQueryServerSink.putMetrics(PhoenixRuntime.getRequestReadMetrics(this.getResultSet())); + this.getResultSet().unwrap(PhoenixResultSet.class).resetMetrics(); + + } + +} diff --git a/phoenix-core/src/main/java/org/apache/phoenix/monitoring/PhoenixQueryServerSink.java b/phoenix-core/src/main/java/org/apache/phoenix/monitoring/PhoenixQueryServerSink.java new file mode 100644 index 00000000000..b997034a6c4 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/monitoring/PhoenixQueryServerSink.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.monitoring; + + +import java.util.Collection; +import java.util.Map; + +/** + * Created by rshrivastava on 2/22/17. + */ +public interface PhoenixQueryServerSink { + + public void close(); + + public void flush(); + + public void init(); + + public void putMetrics(Map> metricsMap); + + public void putMetricsOverall(Map metricsMap); + + public void putGlobalMetrics(Collection globalMetrics); + +} diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java index 2329432bf32..a96c551b3cb 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java @@ -175,6 +175,7 @@ import org.apache.phoenix.iterate.TableResultIterator; import org.apache.phoenix.iterate.TableResultIterator.RenewLeaseStatus; import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.jdbc.PhoenixConnectionPQS; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.jdbc.PhoenixEmbeddedDriver.ConnectionInfo; import org.apache.phoenix.parse.PFunction; @@ -712,7 +713,14 @@ public PhoenixConnection connect(String url, Properties info) throws SQLExceptio PMetaData metadata = latestMetaData; throwConnectionClosedIfNullMetaData(); metadata = metadata.clone(); - return new PhoenixConnection(this, url, info, metadata); + Boolean ifPQS=Boolean.getBoolean(JDBCUtil.findProperty(url,info,QueryServices.PHOENIX_QUERY_SERVER_METRICS)); + if (ifPQS) + { + return new PhoenixConnectionPQS(this,url,info,metadata); + } else { + return new PhoenixConnection(this, url, info, metadata); + } + } diff --git a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/MetricsBindingModule.java b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/MetricsBindingModule.java new file mode 100644 index 00000000000..31760ac4e14 --- /dev/null +++ b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/MetricsBindingModule.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.queryserver.metrics; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; + + +public class MetricsBindingModule extends AbstractModule { + @Override + protected void configure() { + bind(PhoenixQueryServerSink.class).to(PhoenixQueryServerFileSink.class); + } + + @Provides + Configuration getConfiguration() { + Configuration conf=HBaseConfiguration.create(); + return conf; + } +} diff --git a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerFileSink.java b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerFileSink.java new file mode 100644 index 00000000000..eaaad1eb10f --- /dev/null +++ b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerFileSink.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.queryserver.metrics; + + +import com.google.inject.Inject; +import org.apache.hadoop.conf.Configuration; +import org.apache.phoenix.monitoring.GlobalMetric; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; + +import java.util.Collection; +import java.util.Map; + + +public class PhoenixQueryServerFileSink implements PhoenixQueryServerSink { + + + @Inject + Configuration configuration; + + @Override + public void close() { + + } + + @Override + public void flush() { + + } + + @Override + public void init() { + // TBD + //get hold of configuration property + //write out the data to a File + } + + @Override + public void putMetrics(Map> metricsMap) { + System.out.println(metricsMap.toString()); + } + + @Override + public void putMetricsOverall(Map metricsMap) { + System.out.println(metricsMap.toString()); + } + + @Override + public void putGlobalMetrics(Collection globalMetrics) { + System.out.println(globalMetrics.toString()); + } +} diff --git a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerGlobalMetrics.java b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerGlobalMetrics.java new file mode 100644 index 00000000000..52f5b96e561 --- /dev/null +++ b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/metrics/PhoenixQueryServerGlobalMetrics.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.queryserver.metrics; + +import com.google.inject.Inject; +import org.apache.hadoop.conf.Configuration; +import org.apache.phoenix.monitoring.GlobalMetric; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; +import org.apache.phoenix.query.QueryServices; +import org.apache.phoenix.query.QueryServicesOptions; +import org.apache.phoenix.util.PhoenixRuntime; + +import java.util.Collection; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + + +public class PhoenixQueryServerGlobalMetrics { + + @Inject + Configuration configuration; + + @Inject + private PhoenixQueryServerSink phoenixQueryServerSink; + + public void scheduleGlobalMetricsCollection() { + int delay = configuration.getInt(QueryServices.PHOENIX_PQS_GLOBAL_INITIAL_DELAY, + QueryServicesOptions.DEFAULT_PHOENIX_PQS_GLOBAL_INITIAL_DELAY); + int interval = configuration.getInt(QueryServices.PHOENIX_PQS_GLOBAL_PERIOD, + QueryServicesOptions.DEFAULT_PHOENIX_PQS_GLOBAL_PERIOD); + + ScheduledExecutorService service = Executors.newScheduledThreadPool(1); + service.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + Collection metrics = PhoenixRuntime.getGlobalPhoenixClientMetrics(); + phoenixQueryServerSink.putGlobalMetrics(metrics); + + } + }, delay, interval, TimeUnit.SECONDS); + } + + +} diff --git a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java index 8c44938b114..80a5b2ebae4 100644 --- a/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java +++ b/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java @@ -22,6 +22,9 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.inject.Binding; +import com.google.inject.Guice; +import com.google.inject.Injector; import org.apache.calcite.avatica.Meta; import org.apache.calcite.avatica.remote.Driver; import org.apache.calcite.avatica.remote.LocalService; @@ -41,8 +44,12 @@ import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; +import org.apache.phoenix.monitoring.GlobalMetric; +import org.apache.phoenix.monitoring.PhoenixQueryServerSink; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.query.QueryServicesOptions; +import org.apache.phoenix.queryserver.metrics.MetricsBindingModule; +import org.apache.phoenix.queryserver.metrics.PhoenixQueryServerGlobalMetrics; import java.io.File; import java.lang.management.ManagementFactory; @@ -341,7 +348,11 @@ public UserGroupInformation load(String remoteUserName) throws Exception { } public static void main(String[] argv) throws Exception { - int ret = ToolRunner.run(HBaseConfiguration.create(), new QueryServer(), argv); - System.exit(ret); + Injector injector=Guice.createInjector(new MetricsBindingModule()); + PhoenixQueryServerGlobalMetrics phoenixQueryServerGlobalMetrics = injector + .getInstance(PhoenixQueryServerGlobalMetrics.class); + phoenixQueryServerGlobalMetrics.scheduleGlobalMetricsCollection(); + int ret = ToolRunner.run(HBaseConfiguration.create(), new QueryServer(), argv); + System.exit(ret); } }