Yammer metrics to monitor RESTful web services and report them via its admin web
This is a Yammer metrics tutorial to monitor RESTful web services. This extends RESTEasy web service tutorial basic and the basic stand-alone Yammer tutorial.
Step 1: The pom.xml file needs to have relevant dependencies defined relating to Yammer and Spring Web in addition to the JAX-RS librraies that was covered in the previous tutorial.
<!-- Yammer Metrics -->
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-core</artifactId>
<scope>compile</scope>
<version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-annotation</artifactId>
<scope>compile</scope>
<version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-spring</artifactId>
<scope>runtime</scope>
<version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-servlet</artifactId>
<scope>compile</scope>
<version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-web</artifactId>
<scope>runtime</scope>
<version>${metrics.version}</version>
</dependency>
<!-- Servelet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>${javax-servlet.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
<version>${spring.version}</version>
</dependency>
Step 2: Add metrics annotation to the RESTful web service interface and implementation
package com.mytutorial;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import com.yammer.metrics.annotation.ExceptionMetered;
import com.yammer.metrics.annotation.Timed;
@Path("/myapp")
public interface SimpleRestWeb {
@GET
@Path("/name/{name}")
@Timed
@ExceptionMetered
public String sayHello(@PathParam("name") String name);
}
package com.mytutorial; import java.util.concurrent.atomic.AtomicLong; import com.yammer.metrics.annotation.Gauge;
import com.yammer.metrics.annotation.Timed;
public class SimpleRestWebImpl implements SimpleRestWeb {
@Gauge
AtomicLong requestCount = new AtomicLong();
@Override
@Metered
public String sayHello(String name) {
String result = "Hello " + name;
requestCount.incrementAndGet();
return result;
}
}
Note: A gauge "requestCount" was added to count the number of requests.
Step 3: The applicationContext.xml file under com/mytutorial with mterics bootstrapping.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:metrics="http://www.yammer.com/schema/metrics"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.yammer.com/schema/metrics http://www.yammer.com/schema/metrics/metrics.xsd">
<metrics:metrics-registry id="rest-metrics"/>
<metrics:health-check-registry id="rest-health"/>
<metrics:annotation-driven metrics-registry="rest-metrics" health-check-registry="rest-health" proxy-target-class="true" />
<bean id="simpleRestWeb" class="com.mytutorial.SimpleRestWebImpl" />
</beans>
Step 4: The web.xml file with the Yammer admin servlet and relevant listeners defined.
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/com/mytutorial/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>resteasy.use.deployment.sensitive.factory</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.mytutorial.MetricsContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-simple</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet>
<servlet-name>admin-servlet</servlet-name>
<servlet-class>com.yammer.metrics.reporting.AdminServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-simple</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>admin-servlet</servlet-name>
<url-pattern>/admin/*</url-pattern>
</servlet-mapping>
</web-app>
Step 5: The ServletContextListener com.mytutorial.MetricsContextLoaderListener defined in the above web.xml is a custom listener used to make MetricsRegistry available from the spring context to the Yammer admin servlet defined in the above web.xml.
package com.mytutorial;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.yammer.metrics.core.MetricsRegistry;
import com.yammer.metrics.reporting.MetricsServlet;
/**
* Application Lifecycle Listener for Metrics.
*
*I need to fetch the MetricsRegistry from the Spring Context and put it into the ServletContext,
* for the yammer admin-servlet to be able to find it.....
*
*/
public class MetricsContextLoaderListener implements ServletContextListener {
public MetricsContextLoaderListener() {
}
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
MetricsRegistry metricsRegistry = getMetricsRegistry(context);
setMetricsRegistry(metricsRegistry, context);
}
public void contextDestroyed(ServletContextEvent event) {
}
protected MetricsRegistry getMetricsRegistry(ServletContext context) {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(context);
return springContext.getBean(MetricsRegistry.class);
}
protected void setMetricsRegistry(MetricsRegistry registry, ServletContext context) {
context.setAttribute(MetricsServlet.REGISTRY_ATTRIBUTE, registry);
}
}
Step 6: Build and deploy the war file.
Hit the url: http://localhost:8080/tutorial/rest/myapp/name/arul to invoke the RESTful web service.
Hit the url: http://localhost:8080/tutorial/admin/metrics?pretty=true to get the metrics as json String.
Hit the url: http://localhost:8080/tutorial/admin to get the Yammer menu.
Step 7: The json output for metrics (e.g. http://localhost:8080/tutorial/admin/metrics?pretty=true) will look like
{
{
"jvm" : {
"vm" : {
"name" : "Java HotSpot(TM) 64-Bit Server VM",
"version" : "1.6.0_45-b06"
},
"memory" : {
"totalInit" : 2.695299072E9,
"totalUsed" : 2.8351824E8,
"totalMax" : 5.953159168E9,
"totalCommitted" : 2.606497792E9,
"heapInit" : 2.155872256E9,
"heapUsed" : 2.29205536E8,
"heapMax" : 3.780509696E9,
"heapCommitted" : 2.066087936E9,
"heap_usage" : 0.06062821006450872,
"non_heap_usage" : 0.02499863539883529,
"memory_pool_usages" : {
"Code Cache" : 0.06720225016276042,
"PS Eden Space" : 0.16319328855716045,
"PS Old Gen" : 0.009577277144031412,
"PS Perm Gen" : 0.023997800623475327,
"PS Survivor Space" : 0.0
}
},
"daemon_thread_count" : 28,
"thread_count" : 49,
"current_time" : 1395644957593,
"uptime" : 24,
"fd_usage" : "NaN",
"thread-states" : {
"new" : 0.0,
"timed_waiting" : 0.4897959183673469,
"terminated" : 0.0,
"waiting" : 0.16326530612244897,
"blocked" : 0.0,
"runnable" : 0.3469387755102041
},
"garbage-collectors" : {
"PS MarkSweep" : {
"runs" : 2,
"time" : 134
},
"PS Scavenge" : {
"runs" : 2,
"time" : 33
}
}
},
"com.mytutorial.SimpleRestWebImpl" : {
"requestCount" : {
"type" : "gauge",
"value" : 1
},
"sayHello" : {
"type" : "timer",
"duration" : {
"unit" : "milliseconds",
"min" : 2999.710987,
"max" : 2999.710987,
"mean" : 2999.710987,
"std_dev" : 0.0,
"median" : 2999.710987,
"p75" : 2999.710987,
"p95" : 2999.710987,
"p98" : 2999.710987,
"p99" : 2999.710987,
"p999" : 2999.710987
},
"rate" : {
"unit" : "seconds",
"count" : 1,
"mean" : 0.06855060368303201,
"m1" : 0.0,
"m5" : 0.0,
"m15" : 0.0
}
}
}
}
Take note of "requestCount", which counts the number of requests.
Labels: Metrics, Monitoring, Yammer
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home