sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pras...@apache.org
Subject git commit: SENTRY-477: Sentry service should expose metrics (Sravya Tirukkovalur via Prasad Mujumdar)
Date Wed, 29 Oct 2014 18:42:37 GMT
Repository: incubator-sentry
Updated Branches:
  refs/heads/master e4dc61d52 -> de0cc9e7f


SENTRY-477: Sentry service should expose metrics (Sravya Tirukkovalur via Prasad Mujumdar)


Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/de0cc9e7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/de0cc9e7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/de0cc9e7

Branch: refs/heads/master
Commit: de0cc9e7f62c1a44474b196d521b87d1ff902f0e
Parents: e4dc61d
Author: Prasad Mujumdar <prasadm@cloudera.com>
Authored: Wed Oct 29 11:42:28 2014 -0700
Committer: Prasad Mujumdar <prasadm@cloudera.com>
Committed: Wed Oct 29 11:42:28 2014 -0700

----------------------------------------------------------------------
 pom.xml                                         |   6 +-
 sentry-provider/sentry-provider-db/pom.xml      |  25 ++++
 .../db/service/persistent/SentryStore.java      |  42 ++++++
 ...SentryHealthCheckServletContextListener.java |  35 +++++
 .../db/service/thrift/SentryMetrics.java        | 135 +++++++++++++++++++
 .../SentryMetricsServletContextListener.java    |  32 +++++
 .../thrift/SentryPolicyStoreProcessor.java      |  56 ++++++++
 .../db/service/thrift/SentryWebServer.java      |  55 ++++++++
 .../sentry/service/thrift/SentryService.java    |  30 ++++-
 .../sentry/service/thrift/ServiceConstants.java |   8 ++
 .../db/service/persistent/TestSentryStore.java  |  65 +++++++++
 .../AbstractTestWithStaticConfiguration.java    |   2 +
 12 files changed, 486 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index e172e92..405367f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,8 +50,8 @@ limitations under the License.
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compile.source>1.6</maven.compile.source>
-    <maven.compile.target>1.6</maven.compile.target>
+    <maven.compile.source>1.7</maven.compile.source>
+    <maven.compile.target>1.7</maven.compile.target>
     <!-- versions are in alphabetical order -->
     <ant.contrib.version>1.0b3</ant.contrib.version>
     <maven.antrun.plugin.version>1.7</maven.antrun.plugin.version>
@@ -83,6 +83,8 @@ limitations under the License.
     <zookeeper.version>3.4.5-cdh5.1.0-SNAPSHOT</zookeeper.version>
     <pig.version>0.12.0-cdh5.1.0-SNAPSHOT</pig.version>
     <jackson.version>1.8.8</jackson.version>
+    <metrics.version>3.1.0</metrics.version>
+    <jettyVersion>7.6.16.v20140903</jettyVersion>
   </properties>
 
   <dependencyManagement>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/pom.xml b/sentry-provider/sentry-provider-db/pom.xml
index b4167e4..fbf831a 100644
--- a/sentry-provider/sentry-provider-db/pom.xml
+++ b/sentry-provider/sentry-provider-db/pom.xml
@@ -134,6 +134,31 @@ limitations under the License.
       <artifactId>datanucleus-rdbms</artifactId>
     </dependency>
     <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-core</artifactId>
+      <version>${metrics.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-servlets</artifactId>
+      <version>${metrics.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-jvm</artifactId>
+      <version>${metrics.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jettyVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-servlet</artifactId>
+      <version>${jettyVersion}</version>
+    </dependency>
+    <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
index 017cf08..f6699d2 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
@@ -18,6 +18,7 @@
 
 package org.apache.sentry.provider.db.service.persistent;
 
+import com.codahale.metrics.Gauge;
 import static org.apache.sentry.provider.common.ProviderConstants.AUTHORIZABLE_JOINER;
 import static org.apache.sentry.provider.common.ProviderConstants.KV_JOINER;
 
@@ -271,6 +272,47 @@ public class SentryStore {
     }
   }
 
+  private <T> Long getCount(Class<T> tClass) {
+    PersistenceManager pm = null;
+    Long size = new Long(-1);
+    try {
+      pm = openTransaction();
+      Query query = pm.newQuery();
+      query.setClass(tClass);
+      query.setResult("count(this)");
+      size = (Long)query.execute();
+
+    } finally {
+      commitTransaction(pm);
+    }
+    return size;
+  }
+  public Gauge<Long> getRoleCountGauge() {
+    return new Gauge< Long >() {
+      @Override
+      public Long getValue() {
+        return getCount(MSentryRole.class);
+      }
+    };
+  }
+
+  public Gauge<Long> getPrivilegeCountGauge() {
+    return new Gauge< Long >() {
+      @Override
+      public Long getValue() {
+        return getCount(MSentryPrivilege.class);
+      }
+    };
+  }
+  public Gauge<Long> getGroupCountGauge() {
+    return new Gauge< Long >() {
+      @Override
+      public Long getValue() {
+        return getCount(MSentryGroup.class);
+      }
+    };
+  }
+
   public CommitContext alterSentryRoleGrantPrivilege(String grantorPrincipal,
       String roleName, TSentryPrivilege privilege)
       throws SentryUserException {

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java
new file mode 100644
index 0000000..8822c2e
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java
@@ -0,0 +1,35 @@
+/**
+ * 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.sentry.provider.db.service.thrift;
+
+import com.codahale.metrics.health.HealthCheckRegistry;
+import com.codahale.metrics.servlets.HealthCheckServlet;
+
+/**
+ * Use this class's registry to register health checks: Can be some tests which make sure
Sentry service is healthy
+ */
+public class SentryHealthCheckServletContextListener extends HealthCheckServlet.ContextListener
{
+
+  //This is just a place holder for health check registry, with out this AdminServlet throws
out an error
+  public static final HealthCheckRegistry HEALTH_CHECK_REGISTRY = new HealthCheckRegistry();
+
+  @Override
+  protected HealthCheckRegistry getHealthCheckRegistry() {
+    return HEALTH_CHECK_REGISTRY;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java
new file mode 100644
index 0000000..6bd7e2b
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java
@@ -0,0 +1,135 @@
+/**
+ * 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.sentry.provider.db.service.thrift;
+
+import com.codahale.metrics.ConsoleReporter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.MetricSet;
+import com.codahale.metrics.Timer;
+import com.codahale.metrics.jvm.BufferPoolMetricSet;
+import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
+import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
+import com.codahale.metrics.jvm.ThreadStatesGaugeSet;
+import org.apache.sentry.provider.db.service.persistent.SentryStore;
+
+import java.lang.management.ManagementFactory;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A singleton class which holds metrics related utility functions as well as the list of
metrics
+ */
+public class SentryMetrics {
+  private static SentryMetrics sentryMetrics = null;
+  private boolean reportingInitialized = false;
+
+  public final Timer createRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "create-role"));
+  public final Timer dropRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "drop-role"));
+  public final Timer grantRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "grant-role"));
+  public final Timer revokeRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "revoke-role"));
+  public final Timer grantTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "grant-privilege"));
+  public final Timer revokeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "revoke-privilege"));
+
+  public final Timer dropPrivilegeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "drop-privilege"));
+  public final Timer renamePrivilegeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "rename-privilege"));
+
+  public final Timer listRolesByGroupTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-roles-by-group"));
+  public final Timer listPrivilegesByRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-by-role"));
+  public final Timer listPrivilegesForProviderTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-for-provider"));
+  public final Timer listPrivilegesByAuthorizableTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer(
+      MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-by-authorizable"));
+
+  private SentryMetrics() {
+    registerMetricSet("gc", new GarbageCollectorMetricSet(), SentryMetricsServletContextListener.METRIC_REGISTRY);
+    registerMetricSet("buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()),
+        SentryMetricsServletContextListener.METRIC_REGISTRY);
+    registerMetricSet("memory", new MemoryUsageGaugeSet(), SentryMetricsServletContextListener.METRIC_REGISTRY);
+    registerMetricSet("threads", new ThreadStatesGaugeSet(), SentryMetricsServletContextListener.METRIC_REGISTRY);
+  }
+
+  public static synchronized SentryMetrics getInstance() {
+    if (sentryMetrics == null) {
+      sentryMetrics = new SentryMetrics();
+    }
+    return sentryMetrics;
+  }
+
+  public void addSentryStoreGauges(SentryStore sentryStore) {
+    addGauge(SentryStore.class, "role_count", sentryStore.getRoleCountGauge());
+    addGauge(SentryStore.class, "privilege_count", sentryStore.getPrivilegeCountGauge());
+    addGauge(SentryStore.class, "group_count", sentryStore.getGroupCountGauge());
+  }
+
+
+  /* Should be only called once to initialize the reporters
+   */
+  public synchronized void initReporting(Reporting reporting) {
+    if(!reportingInitialized) {
+      switch(reporting) {
+        case CONSOLE:
+          final ConsoleReporter consoleReporter = ConsoleReporter.forRegistry(SentryMetricsServletContextListener.METRIC_REGISTRY)
+              .convertRatesTo(TimeUnit.SECONDS)
+              .convertDurationsTo(TimeUnit.MILLISECONDS)
+              .build();
+          consoleReporter.start(1, TimeUnit.SECONDS);
+          break;
+        case JMX:
+          final JmxReporter jmxReporter = JmxReporter.forRegistry(SentryMetricsServletContextListener.METRIC_REGISTRY)
+              .convertRatesTo(TimeUnit.SECONDS)
+              .convertDurationsTo(TimeUnit.MILLISECONDS)
+              .build();
+          jmxReporter.start();
+          break;
+      }
+    }
+  }
+
+  private <T, V> void addGauge(Class<T> tClass, String gaugeName, Gauge<V>
gauge) {
+    SentryMetricsServletContextListener.METRIC_REGISTRY.register(
+        MetricRegistry.name(tClass, gaugeName), gauge);
+  }
+
+  private void registerMetricSet(String prefix, MetricSet metricSet, MetricRegistry registry)
{
+    for (Map.Entry<String, Metric> entry : metricSet.getMetrics().entrySet()) {
+      if (entry.getValue() instanceof MetricSet) {
+        registerMetricSet(prefix + "." + entry.getKey(), (MetricSet) entry.getValue(), registry);
+      } else {
+        registry.register(prefix + "." + entry.getKey(), entry.getValue());
+      }
+    }
+  }
+
+  public enum Reporting {
+    JMX,
+    CONSOLE;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java
new file mode 100644
index 0000000..6692197
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java
@@ -0,0 +1,32 @@
+/**
+ * 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.sentry.provider.db.service.thrift;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.servlets.MetricsServlet;
+
+public class SentryMetricsServletContextListener extends MetricsServlet.ContextListener {
+
+  public static final MetricRegistry METRIC_REGISTRY = new MetricRegistry();
+
+  @Override
+  protected MetricRegistry getMetricRegistry() {
+    return METRIC_REGISTRY;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
index d64d019..01077da 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 
+import com.codahale.metrics.Timer;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.sentry.SentryUserException;
 import org.apache.sentry.core.model.db.AccessConstants;
@@ -67,6 +68,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   private final NotificationHandlerInvoker notificationHandlerInvoker;
   private final ImmutableSet<String> adminGroups;
   private boolean isReady;
+  SentryMetrics sentryMetrics;
 
   public SentryPolicyStoreProcessor(String name, Configuration conf) throws Exception {
     super();
@@ -79,6 +81,24 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
     isReady = true;
     adminGroups = ImmutableSet.copyOf(toTrimedLower(Sets.newHashSet(conf.getStrings(
         ServerConfig.ADMIN_GROUPS, new String[]{}))));
+    initReporting();
+  }
+
+  private void initReporting() {
+    String sentryReporting = conf.get(ServerConfig.SENTRY_REPORTING);
+    if( sentryReporting != null) {
+      SentryMetrics.Reporting reporting;
+      try {
+        reporting = SentryMetrics.Reporting.valueOf(sentryReporting.toUpperCase());
+        sentryMetrics = SentryMetrics.getInstance();
+        sentryMetrics.addSentryStoreGauges(sentryStore);
+        sentryMetrics.initReporting(reporting);
+
+      } catch (IllegalArgumentException e) {
+        LOGGER.warn("Metrics reporting not configured correctly, please set " + ServerConfig.SENTRY_REPORTING
+
+            " to: " + ServerConfig.SENTRY_REPORTING_CONSOLE + "/" + ServerConfig.SENTRY_REPORTING_JMX);
+      }
+    }
   }
 
   public void stop() {
@@ -148,6 +168,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TCreateSentryRoleResponse create_sentry_role(
     TCreateSentryRoleRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.createRoleTimer.time();
     TCreateSentryRoleResponse response = new TCreateSentryRoleResponse();
     try {
       authorize(request.getRequestorUserName(),
@@ -167,6 +188,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -177,6 +200,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TAlterSentryRoleGrantPrivilegeResponse alter_sentry_role_grant_privilege
   (TAlterSentryRoleGrantPrivilegeRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.grantTimer.time();
 
     TAlterSentryRoleGrantPrivilegeResponse response = new TAlterSentryRoleGrantPrivilegeResponse();
     try {
@@ -201,6 +225,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -211,6 +237,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TAlterSentryRoleRevokePrivilegeResponse alter_sentry_role_revoke_privilege
   (TAlterSentryRoleRevokePrivilegeRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.revokeTimer.time();
     TAlterSentryRoleRevokePrivilegeResponse response = new TAlterSentryRoleRevokePrivilegeResponse();
     try {
       CommitContext commitContext = sentryStore.alterSentryRoleRevokePrivilege(request.getRequestorUserName(),
@@ -237,6 +264,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -247,6 +276,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TDropSentryRoleResponse drop_sentry_role(
     TDropSentryRoleRequest request)  throws TException {
+    final Timer.Context timerContext = sentryMetrics.dropRoleTimer.time();
     TDropSentryRoleResponse response = new TDropSentryRoleResponse();
     TSentryResponseStatus status;
     try {
@@ -267,6 +297,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -277,6 +309,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TAlterSentryRoleAddGroupsResponse alter_sentry_role_add_groups(
     TAlterSentryRoleAddGroupsRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.grantRoleTimer.time();
     TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse();
     try {
       authorize(request.getRequestorUserName(),
@@ -297,6 +330,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -307,6 +342,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TAlterSentryRoleDeleteGroupsResponse alter_sentry_role_delete_groups(
     TAlterSentryRoleDeleteGroupsRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.revokeRoleTimer.time();
     TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse();
     try {
       authorize(request.getRequestorUserName(),
@@ -327,6 +363,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error adding groups to role: " + request;
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
 
     AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
@@ -337,6 +375,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TListSentryRolesResponse list_sentry_roles_by_group(
     TListSentryRolesRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.listRolesByGroupTimer.time();
     TListSentryRolesResponse response = new TListSentryRolesResponse();
     TSentryResponseStatus status;
     Set<TSentryRole> roleSet = new HashSet<TSentryRole>();
@@ -373,6 +412,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
     return response;
   }
@@ -380,6 +421,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TListSentryPrivilegesResponse list_sentry_privileges_by_role(
       TListSentryPrivilegesRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.listPrivilegesByRoleTimer.time();
     TListSentryPrivilegesResponse response = new TListSentryPrivilegesResponse();
     TSentryResponseStatus status;
     Set<TSentryPrivilege> privilegeSet = new HashSet<TSentryPrivilege>();
@@ -413,6 +455,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
     return response;
   }
@@ -424,6 +468,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TListSentryPrivilegesForProviderResponse list_sentry_privileges_for_provider(
       TListSentryPrivilegesForProviderRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.listPrivilegesForProviderTimer.time();
     TListSentryPrivilegesForProviderResponse response = new TListSentryPrivilegesForProviderResponse();
     response.setPrivileges(new HashSet<String>());
     try {
@@ -449,6 +494,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
       String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
     return response;
   }
@@ -495,6 +542,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TDropPrivilegesResponse drop_sentry_privilege(
       TDropPrivilegesRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.dropPrivilegeTimer.time();
     TDropPrivilegesResponse response = new TDropPrivilegesResponse();
     try {
       authorize(request.getRequestorUserName(), adminGroups);
@@ -508,6 +556,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
           + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
     return response;
   }
@@ -515,6 +565,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TRenamePrivilegesResponse rename_sentry_privilege(
       TRenamePrivilegesRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.renamePrivilegeTimer.time();
     TRenamePrivilegesResponse response = new TRenamePrivilegesResponse();
     try {
       authorize(request.getRequestorUserName(), adminGroups);
@@ -529,6 +580,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
           + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.close();
     }
     return response;
   }
@@ -536,6 +589,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
   @Override
   public TListSentryPrivilegesByAuthResponse list_sentry_privileges_by_authorizable(
       TListSentryPrivilegesByAuthRequest request) throws TException {
+    final Timer.Context timerContext = sentryMetrics.listPrivilegesByAuthorizableTimer.time();
     TListSentryPrivilegesByAuthResponse response = new TListSentryPrivilegesByAuthResponse();
     Map<TSentryAuthorizable, TSentryPrivilegeMap> authRoleMap = Maps.newHashMap();
     String subject = request.getRequestorUserName();
@@ -586,6 +640,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface
{
           + e.getMessage();
       LOGGER.error(msg, e);
       response.setStatus(Status.RuntimeError(msg, e));
+    } finally {
+      timerContext.stop();
     }
     return response;
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
new file mode 100644
index 0000000..0243c48
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
@@ -0,0 +1,55 @@
+package org.apache.sentry.provider.db.service.thrift;
+
+/**
+ * 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.
+ */
+
+import com.codahale.metrics.servlets.AdminServlet;
+
+import java.util.EventListener;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import java.util.List;
+
+public class SentryWebServer {
+  Server server;
+  int port;
+
+  public SentryWebServer(List<EventListener> listeners, int port) {
+    this.port = port;
+    server = new Server(port);
+    ServletContextHandler servletContextHandler = new ServletContextHandler();
+    ServletHolder servletHolder =  new ServletHolder(AdminServlet.class);
+    servletContextHandler.addServlet(servletHolder, "/*");
+
+    for(EventListener listener:listeners) {
+      servletContextHandler.addEventListener(listener);
+    }
+
+    server.setHandler(servletContextHandler);
+  }
+
+  public void start() throws Exception{
+    server.start();
+  }
+  public void stop() throws Exception{
+    server.stop();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java
index 40e8a0e..8915b4d 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java
@@ -25,7 +25,10 @@ import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.ServerSocket;
 import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.EventListener;
 import java.util.HashSet;
+import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -45,6 +48,9 @@ import org.apache.hadoop.security.SaslRpcServer;
 import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
 import org.apache.hadoop.security.SecurityUtil;
 import org.apache.sentry.Command;
+import org.apache.sentry.provider.db.service.thrift.SentryHealthCheckServletContextListener;
+import org.apache.sentry.provider.db.service.thrift.SentryMetricsServletContextListener;
+import org.apache.sentry.provider.db.service.thrift.SentryWebServer;
 import org.apache.sentry.service.thrift.ServiceConstants.ConfUtilties;
 import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
 import org.apache.thrift.TMultiplexedProcessor;
@@ -55,12 +61,10 @@ import org.apache.thrift.transport.TSaslServerTransport;
 import org.apache.thrift.transport.TServerSocket;
 import org.apache.thrift.transport.TServerTransport;
 import org.apache.thrift.transport.TTransportFactory;
-import org.mortbay.log.Log;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
 
 public class SentryService implements Callable {
 
@@ -83,6 +87,8 @@ public class SentryService implements Callable {
   private Future future;
   private TServer thriftServer;
   private Status status;
+  private int webServerPort;
+  private SentryWebServer sentryWebServer;
 
   public SentryService(Configuration conf) {
     this.conf = conf;
@@ -133,6 +139,7 @@ public class SentryService implements Callable {
             + (count++));
       }
     });
+    webServerPort = conf.getInt(ServerConfig.SENTRY_WEB_PORT, ServerConfig.SENTRY_WEB_PORT_DEFAULT);
     status = Status.NOT_STARTED;
   }
 
@@ -210,9 +217,25 @@ public class SentryService implements Callable {
         .minWorkerThreads(minThreads).maxWorkerThreads(maxThreads);
     thriftServer = new TThreadPoolServer(args);
     LOGGER.info("Serving on " + address);
+    startSentryWebServer();
     thriftServer.serve();
   }
 
+  private void startSentryWebServer() throws Exception{
+    List<EventListener> listenerList = new ArrayList<EventListener>();
+    listenerList.add(new SentryHealthCheckServletContextListener());
+    listenerList.add(new SentryMetricsServletContextListener());
+    sentryWebServer = new SentryWebServer(listenerList, webServerPort);
+    sentryWebServer.start();
+
+  }
+
+  private void stopSentryWebServer() throws Exception{
+    if( sentryWebServer != null) {
+      sentryWebServer.stop();
+    }
+  }
+
   public InetSocketAddress getAddress() {
     return address;
   }
@@ -231,7 +254,7 @@ public class SentryService implements Callable {
     future = serviceExecutor.submit(this);
   }
 
-  public synchronized void stop() {
+  public synchronized void stop() throws Exception{
     if (status == Status.NOT_STARTED) {
       return;
     }
@@ -241,6 +264,7 @@ public class SentryService implements Callable {
       thriftServer.stop();
     }
     thriftServer = null;
+    stopSentryWebServer();
     status = Status.NOT_STARTED;
     LOGGER.info("Stopped...");
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java
index 52eaeed..29a7a1c 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java
@@ -24,6 +24,7 @@ import javax.security.sasl.Sasl;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableMap;
+import org.apache.sentry.provider.db.service.thrift.SentryMetrics;
 
 public class ServiceConstants {
 
@@ -122,6 +123,13 @@ public class ServiceConstants {
     .put("javax.jdo.option.Multithreaded", "true")
     .build();
 
+    public static final String SENTRY_WEB_PORT = "sentry.service.web.port";
+    public static final int SENTRY_WEB_PORT_DEFAULT = 51000;
+    public static final String SENTRY_REPORTING = "sentry.service.reporting";
+    public static final String SENTRY_REPORTING_JMX = SentryMetrics.Reporting.JMX.name();
//case insensitive
+    public static final String SENTRY_REPORTING_CONSOLE = SentryMetrics.Reporting.CONSOLE.name();//case
insensitive
+
+
   }
   public static class ClientConfig {
     public static final ImmutableMap<String, String> SASL_PROPERTIES = ServiceConstants.SASL_PROPERTIES;

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
index befecf4..2e829d6 100644
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
+++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
@@ -157,6 +157,7 @@ public class TestSentryStore {
       // expected
     }
   }
+
   @Test
   public void testCaseSensitiveScope() throws Exception {
     String roleName = "role1";
@@ -840,6 +841,69 @@ public class TestSentryStore {
     }
   }
 
+  @Test
+  public void testSentryRoleSize() throws Exception {
+    for( long i = 0; i< 5; i++ ) {
+      assertEquals((Long)i, sentryStore.getRoleCountGauge().getValue());
+      sentryStore.createSentryRole("role" + i);
+    }
+  }
+  @Test
+  public void testSentryPrivilegeSize() throws Exception {
+    String role1 = "role1";
+    String role2 = "role2";
+
+    sentryStore.createSentryRole(role1);
+    sentryStore.createSentryRole(role2);
+
+    TSentryPrivilege privilege = new TSentryPrivilege();
+    privilege.setPrivilegeScope("TABLE");
+    privilege.setServerName("server1");
+    privilege.setDbName("db1");
+    privilege.setTableName("tb1");
+    privilege.setCreateTime(System.currentTimeMillis());
+
+    String grantor = "g1";
+
+    assertEquals(new Long(0), sentryStore.getPrivilegeCountGauge().getValue());
+
+    sentryStore.alterSentryRoleGrantPrivilege(grantor, role1, privilege);
+    assertEquals(new Long(1), sentryStore.getPrivilegeCountGauge().getValue());
+
+    sentryStore.alterSentryRoleGrantPrivilege(grantor, role2, privilege);
+    assertEquals(new Long(1), sentryStore.getPrivilegeCountGauge().getValue());
+
+    privilege.setTableName("tb2");
+    sentryStore.alterSentryRoleGrantPrivilege(grantor, role2, privilege);
+    assertEquals(new Long(2), sentryStore.getPrivilegeCountGauge().getValue());
+  }
+
+  @Test
+  public void testSentryGroupsSize() throws Exception {
+    String role1 = "role1";
+    String role2 = "role2";
+
+    sentryStore.createSentryRole(role1);
+    sentryStore.createSentryRole(role2);
+
+    Set<TSentryGroup> groups = Sets.newHashSet();
+    TSentryGroup group = new TSentryGroup();
+    group.setGroupName("group1");
+    groups.add(group);
+
+    String grantor = "g1";
+
+    sentryStore.alterSentryRoleAddGroups(grantor, role1, groups);
+    assertEquals(new Long(1), sentryStore.getGroupCountGauge().getValue());
+
+    sentryStore.alterSentryRoleAddGroups(grantor, role2, groups);
+    assertEquals(new Long(1), sentryStore.getGroupCountGauge().getValue());
+
+    groups.add(new TSentryGroup("group2"));
+    sentryStore.alterSentryRoleAddGroups(grantor, role2, groups);
+    assertEquals(new Long(2), sentryStore.getGroupCountGauge().getValue());
+
+  }
   protected void addGroupsToUser(String user, String... groupNames) {
     policyFile.addGroupsToUser(user, groupNames);
   }
@@ -847,4 +911,5 @@ public class TestSentryStore {
   protected void writePolicyFile() throws Exception {
     policyFile.write(policyFilePath);
   }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/de0cc9e7/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
index f251ebc..f6b6ad4 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
@@ -360,6 +360,7 @@ public abstract class AbstractTestWithStaticConfiguration {
     for (Map.Entry<String, String> entry : properties.entrySet()) {
       sentryConf.set(entry.getKey(), entry.getValue());
     }
+    sentryConf.set(ServerConfig.SENTRY_REPORTING, ServerConfig.SENTRY_REPORTING_CONSOLE);
     sentryServer = new SentryServiceFactory().create(sentryConf);
     properties.put(ClientConfig.SERVER_RPC_ADDRESS, sentryServer.getAddress()
         .getHostName());
@@ -374,6 +375,7 @@ public abstract class AbstractTestWithStaticConfiguration {
       properties.put(HiveConf.ConfVars.METASTORE_EVENT_LISTENERS.varname,
           SentryMetastorePostEventListener.class.getName());
     }
+
   }
 
   private static void startSentryService() throws Exception {


Mime
View raw message