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