knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject knox git commit: KNOX-940 - Support REST access exposing metrics (Mohammad Kamrul Islam via Sandeep More)
Date Sat, 10 Jun 2017 04:22:01 GMT
Repository: knox
Updated Branches:
  refs/heads/master 1ecb6934a -> b13c21a45


KNOX-940 - Support REST access exposing metrics (Mohammad Kamrul Islam via Sandeep More)


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

Branch: refs/heads/master
Commit: b13c21a45a9983d6ba0339da6e18172aa102f45d
Parents: 1ecb693
Author: Sandeep More <more@apache.org>
Authored: Sat Jun 10 00:21:45 2017 -0400
Committer: Sandeep More <more@apache.org>
Committed: Sat Jun 10 00:21:45 2017 -0400

----------------------------------------------------------------------
 gateway-release/pom.xml                         |   4 +
 gateway-server/pom.xml                          |   4 +
 .../services/DefaultGatewayServices.java        |   1 +
 .../GatewayMetricsServletContextListener.java   |  31 +++
 .../metrics/impl/DefaultMetricsService.java     |   5 +-
 gateway-service-health/pom.xml                  |  76 ++++++
 .../service/health/HealthServiceMessages.java   |  32 +++
 .../gateway/service/health/MetricsResource.java | 142 ++++++++++++
 .../gateway/service/health/PingResource.java    |  93 ++++++++
 .../HealthServiceDeploymentContributor.java     |  55 +++++
 ....gateway.deploy.ServiceDeploymentContributor |  19 ++
 .../service/health/MetricsResourceTest.java     |  32 +++
 .../service/health/PingResourceTest.java        |  30 +++
 .../hadoop/gateway/GatewayHealthFuncTest.java   | 229 +++++++++++++++++++
 .../deploy/DeploymentFactoryFuncTest.java       |   7 +-
 pom.xml                                         |  16 ++
 16 files changed, 772 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-release/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index 427faa5..c51f190 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -212,6 +212,10 @@
         </dependency>
         <dependency>
             <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-service-health</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
             <artifactId>gateway-provider-rewrite</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-server/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-server/pom.xml b/gateway-server/pom.xml
index 76fe0b2..e8a6cd4 100644
--- a/gateway-server/pom.xml
+++ b/gateway-server/pom.xml
@@ -328,6 +328,10 @@
             <artifactId>xmltool</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>io.dropwizard.metrics</groupId>
+            <artifactId>metrics-servlets</artifactId>
+        </dependency>
 
     </dependencies>
 

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
index e0c843a..cefada1 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
@@ -219,5 +219,6 @@ public class DefaultGatewayServices implements GatewayServices {
   public void finalizeContribution(DeploymentContext context) {
     // Tell the provider the location of the descriptor.
     context.getWebAppDescriptor().createListener().listenerClass( GatewayServicesContextListener.class.getName()
);
+    context.getWebAppDescriptor().createListener().listenerClass(GatewayMetricsServletContextListener.class.getName());
   }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-server/src/main/java/org/apache/hadoop/gateway/services/GatewayMetricsServletContextListener.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/GatewayMetricsServletContextListener.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/GatewayMetricsServletContextListener.java
new file mode 100644
index 0000000..f0aac21
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/GatewayMetricsServletContextListener.java
@@ -0,0 +1,31 @@
+/**
+ * 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.hadoop.gateway.services;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.servlets.MetricsServlet;
+import org.apache.hadoop.gateway.services.metrics.impl.DefaultMetricsService;
+
+public class GatewayMetricsServletContextListener extends MetricsServlet.ContextListener
{
+
+  @Override
+  protected MetricRegistry getMetricRegistry() {
+    return DefaultMetricsService.getMetricRegistry();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-server/src/main/java/org/apache/hadoop/gateway/services/metrics/impl/DefaultMetricsService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/metrics/impl/DefaultMetricsService.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/metrics/impl/DefaultMetricsService.java
index 0fa8a44..c2a461a 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/metrics/impl/DefaultMetricsService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/metrics/impl/DefaultMetricsService.java
@@ -38,7 +38,7 @@ import java.util.ServiceLoader;
 public class DefaultMetricsService implements MetricsService {
   private static GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
 
-  private final MetricRegistry metrics = new MetricRegistry();
+  private static final MetricRegistry metrics = new MetricRegistry();
 
   public static final String METRICS_REGISTRY = "metrics-registry";
 
@@ -48,7 +48,7 @@ public class DefaultMetricsService implements MetricsService {
 
   private MetricsContext context;
 
-  public MetricRegistry getMetricRegistry() {
+  public static MetricRegistry getMetricRegistry() {
     return metrics;
   }
 
@@ -139,4 +139,5 @@ public class DefaultMetricsService implements MetricsService {
   public MetricsContext getContext() {
     return context;
   }
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-service-health/pom.xml b/gateway-service-health/pom.xml
new file mode 100644
index 0000000..807e50d
--- /dev/null
+++ b/gateway-service-health/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.knox</groupId>
+        <artifactId>gateway</artifactId>
+        <version>0.13.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.knox</groupId>
+    <artifactId>gateway-service-health</artifactId>
+    <version>0.13.0-SNAPSHOT</version>
+    <name>gateway-service-health</name>
+    <url>http://maven.apache.org</url>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-util-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-provider-rewrite</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-provider-jersey</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-test-utils</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.dropwizard.metrics</groupId>
+            <artifactId>metrics-servlets</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.knox</groupId>
+            <artifactId>gateway-server</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/HealthServiceMessages.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/HealthServiceMessages.java
b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/HealthServiceMessages.java
new file mode 100644
index 0000000..2cce193
--- /dev/null
+++ b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/HealthServiceMessages.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.hadoop.gateway.service.health;
+
+import org.apache.hadoop.gateway.i18n.messages.Message;
+import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
+import org.apache.hadoop.gateway.i18n.messages.Messages;
+import org.apache.hadoop.gateway.i18n.messages.StackTrace;
+
+@Messages(logger = "org.apache.hadoop.gateway.service.health")
+public interface HealthServiceMessages {
+  @Message(level = MessageLevel.INFO, text = "{0}")
+  void basicInfo(String original);
+
+  @Message(level = MessageLevel.ERROR, text = "Unable to get health stats for {0}, due to
{1}")
+  void logException(String name, @StackTrace(level = MessageLevel.DEBUG) Exception e);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/MetricsResource.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/MetricsResource.java
b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/MetricsResource.java
new file mode 100644
index 0000000..ddb9c6f
--- /dev/null
+++ b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/MetricsResource.java
@@ -0,0 +1,142 @@
+/**
+ * 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.hadoop.gateway.service.health;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.json.MetricsModule;
+import com.codahale.metrics.servlets.MetricsServlet;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+@Path(MetricsResource.RESOURCE_PATH)
+public class MetricsResource {
+  static final String VERSION_TAG = "v1";
+  static final String RESOURCE_PATH = "/" + VERSION_TAG + "/metrics";
+  private static HealthServiceMessages log = MessagesFactory.get(HealthServiceMessages.class);
+  public static final String RATE_UNIT = MetricsServlet.class.getCanonicalName() + ".rateUnit";
+  public static final String DURATION_UNIT = MetricsServlet.class.getCanonicalName() + ".durationUnit";
+  public static final String SHOW_SAMPLES = MetricsServlet.class.getCanonicalName() + ".showSamples";
+  public static final String METRICS_REGISTRY = MetricsServlet.class.getCanonicalName() +
".registry";
+  public static final String ALLOWED_ORIGIN = MetricsServlet.class.getCanonicalName() + ".allowedOrigin";
+  private static final String CONTENT_TYPE = "application/json";
+
+  private String allowedOrigin;
+  private transient MetricRegistry registry;
+  private transient ObjectMapper mapper;
+
+  @Context
+  private HttpServletRequest request;
+
+  @Context
+  private HttpServletResponse response;
+
+  @Context
+  ServletContext context;
+
+  @PostConstruct
+  public void init() {
+    if (null == registry) {
+      final Object registryAttr = context.getAttribute(METRICS_REGISTRY);
+      if (registryAttr instanceof MetricRegistry) {
+        this.registry = (MetricRegistry) registryAttr;
+      } else {
+        throw new IllegalStateException(String.format("Couldn't find a MetricRegistry instance
with key %s",
+            METRICS_REGISTRY));
+      }
+    }
+    final TimeUnit rateUnit = parseTimeUnit(context.getInitParameter(RATE_UNIT),
+        TimeUnit.SECONDS);
+    final TimeUnit durationUnit = parseTimeUnit(context.getInitParameter(DURATION_UNIT),
+        TimeUnit.SECONDS);
+    final boolean showSamples = Boolean.parseBoolean(context.getInitParameter(SHOW_SAMPLES));
+    this.mapper = new ObjectMapper().registerModule(new MetricsModule(rateUnit, durationUnit,
+        showSamples));
+    this.allowedOrigin = context.getInitParameter(ALLOWED_ORIGIN);
+    log.basicInfo(String.format("Successfully initialized the registry '%s'", METRICS_REGISTRY));
+  }
+
+  @GET
+  @Produces({APPLICATION_JSON, APPLICATION_XML})
+  public Response doGet() {
+    return getMetrics();
+  }
+
+  @POST
+  @Produces({APPLICATION_JSON, APPLICATION_XML})
+  public Response doPost() {
+    return getMetrics();
+  }
+
+  private Response getMetrics() {
+    try {
+      response.setContentType(CONTENT_TYPE);
+      if (allowedOrigin != null) {
+        response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
+      }
+      response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
+      response.setStatus(HttpServletResponse.SC_OK);
+
+      final OutputStream output = response.getOutputStream();
+      try {
+        getWriter(request).writeValue(output, registry);
+      } finally {
+        output.close();
+      }
+    } catch (IOException ioe) {
+      log.logException("metrics", ioe);
+      return Response.serverError().entity(String.format("Failed to reply correctly due to
: %s ", ioe)).build();
+    }
+    return Response.ok().build();
+  }
+
+  private ObjectWriter getWriter(HttpServletRequest request) {
+    final boolean prettyPrint = Boolean.parseBoolean(request.getParameter("pretty"));
+    if (prettyPrint) {
+      return mapper.writerWithDefaultPrettyPrinter();
+    }
+    return mapper.writer();
+  }
+
+
+  TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
+    try {
+      return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
+    } catch (IllegalArgumentException e) {
+      return defaultValue;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/PingResource.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/PingResource.java
b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/PingResource.java
new file mode 100644
index 0000000..d3928b8
--- /dev/null
+++ b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/PingResource.java
@@ -0,0 +1,93 @@
+/**
+ * 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.hadoop.gateway.service.health;
+
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+
+
+@Path(PingResource.RESOURCE_PATH)
+public class PingResource {
+  static final String VERSION_TAG = "v1";
+  static final String RESOURCE_PATH = "/" + VERSION_TAG + "/ping";
+  public static final String CONTENT = "OK";
+  private static HealthServiceMessages log = MessagesFactory.get(HealthServiceMessages.class);
+  private static final String CONTENT_TYPE = "text/plain";
+  private static final String CACHE_CONTROL = "Cache-Control";
+  private static final String NO_CACHE = "must-revalidate,no-cache,no-store";
+
+  @Context
+  HttpServletRequest request;
+
+  @Context
+  private HttpServletResponse response;
+
+  @Context
+  ServletContext context;
+
+  @GET
+  @Produces({APPLICATION_JSON, TEXT_PLAIN})
+  public Response doGet() {
+    return getPingResponse();
+  }
+
+  @POST
+  @Produces({APPLICATION_JSON, TEXT_PLAIN})
+  public Response doPost() {
+    return getPingResponse();
+  }
+
+  private Response getPingResponse() {
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setHeader(CACHE_CONTROL, NO_CACHE);
+    response.setContentType(CONTENT_TYPE);
+    PrintWriter writer = null;
+    try {
+      writer = response.getWriter();
+      writer.println(getPingContent());
+    } catch (IOException ioe) {
+      log.logException("ping", ioe);
+      return Response.serverError().entity(String.format("Failed to reply correctly due to
: %s ", ioe)).build();
+    } finally {
+      if (writer != null) {
+        writer.close();
+      }
+    }
+    return Response.ok().build();
+  }
+
+  String getPingContent() {
+    return CONTENT;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/deploy/HealthServiceDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/deploy/HealthServiceDeploymentContributor.java
b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/deploy/HealthServiceDeploymentContributor.java
new file mode 100644
index 0000000..0228588
--- /dev/null
+++ b/gateway-service-health/src/main/java/org/apache/hadoop/gateway/service/health/deploy/HealthServiceDeploymentContributor.java
@@ -0,0 +1,55 @@
+/**
+ * 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.hadoop.gateway.service.health.deploy;
+
+import org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase;
+
+public class HealthServiceDeploymentContributor extends JerseyServiceDeploymentContributorBase
{
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getRole()
+   */
+  @Override
+  public String getRole() {
+    return "HEALTH";
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getName()
+   */
+  @Override
+  public String getName() {
+    return "HealthService";
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPackages()
+   */
+  @Override
+  protected String[] getPackages() {
+    return new String[]{"org.apache.hadoop.gateway.service.health"};
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPatterns()
+   */
+  @Override
+  protected String[] getPatterns() {
+    return new String[]{"*/**?**"};
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
b/gateway-service-health/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
new file mode 100644
index 0000000..2e81e2a
--- /dev/null
+++ b/gateway-service-health/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
@@ -0,0 +1,19 @@
+##########################################################################
+# 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.
+##########################################################################
+
+org.apache.hadoop.gateway.service.health.deploy.HealthServiceDeploymentContributor
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/MetricsResourceTest.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/MetricsResourceTest.java
b/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/MetricsResourceTest.java
new file mode 100644
index 0000000..a0690fe
--- /dev/null
+++ b/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/MetricsResourceTest.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.hadoop.gateway.service.health;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+public class MetricsResourceTest {
+  @Test
+  public void testPingContent() {
+    MetricsResource mr = new MetricsResource();
+    Assert.assertEquals(mr.parseTimeUnit("MINUTE", TimeUnit.SECONDS), TimeUnit.SECONDS);
+    Assert.assertEquals(mr.parseTimeUnit("MINUTES", TimeUnit.SECONDS), TimeUnit.MINUTES);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/PingResourceTest.java
----------------------------------------------------------------------
diff --git a/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/PingResourceTest.java
b/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/PingResourceTest.java
new file mode 100644
index 0000000..1089e2a
--- /dev/null
+++ b/gateway-service-health/src/test/java/org/apache/hadoop/gateway/service/health/PingResourceTest.java
@@ -0,0 +1,30 @@
+/**
+ * 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.hadoop.gateway.service.health;
+
+import org.apache.hadoop.gateway.service.health.PingResource;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PingResourceTest {
+  @Test
+  public void testPingCdoGetontent() {
+    PingResource pr = new PingResource();
+    Assert.assertEquals(pr.getPingContent(), pr.CONTENT);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayHealthFuncTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayHealthFuncTest.java
b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayHealthFuncTest.java
new file mode 100644
index 0000000..f78d309
--- /dev/null
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayHealthFuncTest.java
@@ -0,0 +1,229 @@
+/**
+ * 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.hadoop.gateway;
+
+import com.jayway.restassured.path.json.JsonPath;
+import com.mycila.xmltool.XMLDoc;
+import com.mycila.xmltool.XMLTag;
+import org.apache.directory.server.protocol.shared.transport.TcpTransport;
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.security.ldap.SimpleLdapDirectoryServer;
+import org.apache.hadoop.gateway.services.DefaultGatewayServices;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.test.TestUtils;
+import org.apache.http.HttpStatus;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+import static com.jayway.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class GatewayHealthFuncTest {
+
+  private static Class RESOURCE_BASE_CLASS = GatewayAdminFuncTest.class;
+  private static Logger LOG = LoggerFactory.getLogger(GatewayAdminFuncTest.class);
+
+  public static GatewayConfig config;
+  public static GatewayServer gateway;
+  public static String gatewayUrl;
+  public static String clusterUrl;
+  public static SimpleLdapDirectoryServer ldap;
+  public static TcpTransport ldapTransport;
+
+  @BeforeClass
+  public static void setupSuite() throws Exception {
+    TestUtils.LOG_ENTER();
+    setupLdap();
+    setupGateway();
+    TestUtils.LOG_EXIT();
+  }
+
+  @AfterClass
+  public static void cleanupSuite() throws Exception {
+    TestUtils.LOG_ENTER();
+    gateway.stop();
+    ldap.stop(true);
+    TestUtils.LOG_EXIT();
+  }
+
+  public static void setupLdap() throws Exception {
+    String basedir = System.getProperty("basedir");
+    if (basedir == null) {
+      basedir = new File(".").getCanonicalPath();
+    }
+
+    final Path path = FileSystems
+        .getDefault().getPath(basedir, "/src/test/resources/users.ldif");
+
+    ldapTransport = new TcpTransport(0);
+    ldap = new SimpleLdapDirectoryServer("dc=hadoop,dc=apache,dc=org", path.toFile(), ldapTransport);
+    ldap.start();
+    LOG.info("LDAP port = " + ldapTransport.getPort());
+  }
+
+  public static void setupGateway() throws Exception {
+
+    File targetDir = new File(System.getProperty("user.dir"), "target");
+    File gatewayDir = new File(targetDir, "gateway-home-" + UUID.randomUUID());
+    gatewayDir.mkdirs();
+
+    GatewayTestConfig testConfig = new GatewayTestConfig();
+    config = testConfig;
+    testConfig.setGatewayHomeDir(gatewayDir.getAbsolutePath());
+
+    File topoDir = new File(testConfig.getGatewayTopologyDir());
+    topoDir.mkdirs();
+
+    File deployDir = new File(testConfig.getGatewayDeploymentDir());
+    deployDir.mkdirs();
+
+    File descriptor = new File(topoDir, "test-cluster.xml");
+    FileOutputStream stream = new FileOutputStream(descriptor);
+    createTopology().toStream(stream);
+    stream.close();
+
+    DefaultGatewayServices srvcs = new DefaultGatewayServices();
+    Map<String, String> options = new HashMap<String, String>();
+    options.put("persist-master", "false");
+    options.put("master", "password");
+    try {
+      srvcs.init(testConfig, options);
+    } catch (ServiceLifecycleException e) {
+      e.printStackTrace(); // I18N not required.
+    }
+    gateway = GatewayServer.startGateway(testConfig, srvcs);
+    MatcherAssert.assertThat("Failed to start gateway.", gateway, notNullValue());
+
+    LOG.info("Gateway port = " + gateway.getAddresses()[0].getPort());
+
+    gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath();
+    clusterUrl = gatewayUrl + "/test-cluster";
+  }
+
+  private static XMLTag createTopology() {
+    XMLTag xml = XMLDoc.newDocument(true)
+        .addRoot("topology")
+        .addTag("gateway")
+        .addTag("provider")
+        .addTag("role").addText("authentication")
+        .addTag("name").addText("ShiroProvider")
+        .addTag("enabled").addText("true")
+        .addTag("param")
+        .addTag("name").addText("main.ldapRealm")
+        .addTag("value").addText("org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm").gotoParent()
+        .addTag("param")
+        .addTag("name").addText("main.ldapRealm.userDnTemplate")
+        .addTag("value").addText("uid={0},ou=people,dc=hadoop,dc=apache,dc=org").gotoParent()
+        .addTag("param")
+        .addTag("name").addText("main.ldapRealm.contextFactory.url")
+        .addTag("value").addText("ldap://localhost:" + ldapTransport.getAcceptor().getLocalAddress().getPort()).gotoParent()
+        .addTag("param")
+        .addTag("name").addText("main.ldapRealm.contextFactory.authenticationMechanism")
+        .addTag("value").addText("simple").gotoParent()
+        .addTag("param")
+        .addTag("name").addText("urls./**")
+        .addTag("value").addText("authcBasic").gotoParent().gotoParent()
+        .addTag("provider")
+        .addTag("role").addText("identity-assertion")
+        .addTag("enabled").addText("true")
+        .addTag("name").addText("Default").gotoParent()
+        .addTag("provider")
+        .gotoRoot()
+        .addTag("service")
+        .addTag("role").addText("HEALTH")
+        .gotoRoot();
+    return xml;
+  }
+
+  public static InputStream getResourceStream(String resource) throws IOException {
+    return getResourceUrl(resource).openStream();
+  }
+
+  public static URL getResourceUrl(String resource) {
+    URL url = ClassLoader.getSystemResource(getResourceName(resource));
+    assertThat("Failed to find test resource " + resource, url, Matchers.notNullValue());
+    return url;
+  }
+
+  public static String getResourceName(String resource) {
+    return getResourceBaseName() + resource;
+  }
+
+  public static String getResourceBaseName() {
+    return RESOURCE_BASE_CLASS.getName().replaceAll("\\.", "/") + "/";
+  }
+
+  @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
+  public void testPingResource() {
+    TestUtils.LOG_ENTER();
+    String username = "guest";
+    String password = "guest-password";
+    String serviceUrl = clusterUrl + "/v1/ping";
+    String body = given()
+        .auth().preemptive().basic(username, password)
+        .header("Accept", MediaType.TEXT_PLAIN)
+        .expect()
+        .statusCode(HttpStatus.SC_OK)
+        .contentType(MediaType.TEXT_PLAIN)
+        .when().get(serviceUrl).asString();
+    Assert.assertEquals("OK", body.trim());
+    TestUtils.LOG_EXIT();
+  }
+
+  @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
+  public void testMetricsResource() {
+    TestUtils.LOG_ENTER();
+    String username = "guest";
+    String password = "guest-password";
+    String serviceUrl = clusterUrl + "/v1/metrics";
+    String body = given()
+        .auth().preemptive().basic(username, password)
+        .expect()
+        .statusCode(HttpStatus.SC_OK)
+        .contentType(MediaType.APPLICATION_JSON)
+        .when().get(serviceUrl).asString();
+    String version = JsonPath.from(body).getString("version");
+    Map<String, String> hm = JsonPath.from(body).getMap("");
+    Assert.assertTrue(hm.size() >= 6);
+    Assert.assertTrue(hm.keySet().containsAll(new HashSet<String>(Arrays.asList(new
String[]{"timers", "histograms",
+        "counters", "gauges", "version", "meters"}))));
+    TestUtils.LOG_EXIT();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/gateway-test/src/test/java/org/apache/hadoop/gateway/deploy/DeploymentFactoryFuncTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/deploy/DeploymentFactoryFuncTest.java
b/gateway-test/src/test/java/org/apache/hadoop/gateway/deploy/DeploymentFactoryFuncTest.java
index 3d8a8df..6ccc934 100644
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/deploy/DeploymentFactoryFuncTest.java
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/deploy/DeploymentFactoryFuncTest.java
@@ -397,8 +397,11 @@ public class DeploymentFactoryFuncTest {
       assertThat(web, hasXPath("/web-app/servlet-mapping/url-pattern", equalTo("/*")));
       //testing the order of listener classes generated
       assertThat(web, hasXPath("/web-app/listener[2]/listener-class", equalTo("org.apache.hadoop.gateway.services.GatewayServicesContextListener")));
-      assertThat(web, hasXPath("/web-app/listener[3]/listener-class", equalTo("org.apache.hadoop.gateway.ha.provider.HaServletContextListener")));
-      assertThat(web, hasXPath("/web-app/listener[4]/listener-class", equalTo("org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteServletContextListener")));
+      assertThat(web, hasXPath("/web-app/listener[3]/listener-class", equalTo("org.apache.hadoop.gateway.services.GatewayMetricsServletContextListener")));
+      assertThat(web, hasXPath("/web-app/listener[4]/listener-class", equalTo("org.apache.hadoop.gateway.ha.provider"
+
+          ".HaServletContextListener")));
+     assertThat(web, hasXPath("/web-app/listener[5]/listener-class", equalTo("org.apache.hadoop.gateway.filter"
+
+         ".rewrite.api.UrlRewriteServletContextListener")));
    }
 
   @Test( timeout = LONG_TIMEOUT )

http://git-wip-us.apache.org/repos/asf/knox/blob/b13c21a4/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 3383caf..5b9531e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
         <module>gateway-service-knoxsso</module>
         <module>gateway-service-knoxssout</module>
         <module>gateway-service-knoxtoken</module>
+        <module>gateway-service-health</module>
         <module>gateway-service-webhdfs</module>
         <module>gateway-service-tgs</module>
         <module>gateway-service-rm</module>
@@ -418,6 +419,11 @@
         <dependencies>
             <dependency>
                 <groupId>${gateway-group}</groupId>
+                <artifactId>gateway-server</artifactId>
+                <version>${gateway-version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${gateway-group}</groupId>
                 <artifactId>gateway-util-common</artifactId>
                 <version>${gateway-version}</version>
             </dependency>
@@ -598,6 +604,11 @@
             </dependency>
             <dependency>
                 <groupId>${gateway-group}</groupId>
+                <artifactId>gateway-service-health</artifactId>
+                <version>${gateway-version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${gateway-group}</groupId>
                 <artifactId>gateway-service-admin</artifactId>
                 <version>${gateway-version}</version>
             </dependency>
@@ -1201,6 +1212,11 @@
             </dependency>
             <dependency>
                 <groupId>io.dropwizard.metrics</groupId>
+                <artifactId>metrics-servlets</artifactId>
+                <version>${metrics-version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.dropwizard.metrics</groupId>
                 <artifactId>metrics-httpclient</artifactId>
                 <version>${metrics-version}</version>
             </dependency>


Mime
View raw message