Advanced monitoring in GlassFish v3

Advanced Monitoring in GlassFish v3
Monitoring in GlassFish v3 has never been so easy and powerful. I am going to talk about an advanced monitoring feature in v3.  Before we get there, some notes to go over first.
  1. Please refer to my earlier blog on Monitoring in GlassFish v3, for in depth details on what all features we have in v3.
  2. Please refer to my another blog on how to make your Application monitoring in the v3 environment
  3. Refer to 'Making a Module monitorable' which will server as a cookbook to make a 3rd party module bring in their own monitoring into v3 using our Monitoring infrastructure
  4. Guildelines on writing Probes and StatsProviders is here
  5. And finally a presentation on writing probes and collecting stats is here

An important feature of Monitoring is that you can write your probes (events) in any component and be able to listen to them in any other component. The component can be a container, module or even a user Application. I will use a sample WebApp which is an enhanced version (Thanks to Byron) of what we used for my ealier blog on "Making your Application monitorable in GlassFish v3"

I am going to show you how to write an App which will not only collect the monitoring data for the requests that are coming in, but would also listen to the events from HTTP Service component and will determine the (average) time taken to serve each of these requests to the App.

The WebApp we are going to use consists of a Servlet, StatsProvider (MyProbeListener) and a pom.xml. You can either download the war or the sources from this zip.

For this App we will not have any Probes, but what we want is a StatsProvider consisting of several ProbeListeners listening to the probes emitted by the HTTP service component.

Following is how our StatsProvider would look like

@ManagedObject
public class MyProbeListener {
    HashMap<Long, Long> requestMap = new HashMap();
    private AverageRangeStatisticImpl averageRequestTime =
            new AverageRangeStatisticImpl(0L, Long.MIN_VALUE, Long.MAX_VALUE, "TotalRequestTime",
                    AverageRangeStatisticImpl.UNIT_MILLISECOND, "Average request time",
                    0L, -1L);

    @ManagedAttribute(id="averageRequestTime")
    public AverageRangeStatistic getAverageRequestTime() {
        return averageRequestTime;
    }

    @ProbeListener("glassfish:web:http-service:requestStartEvent")
    public void requestStart(
         @ProbeParam("appName") String s,
         @ProbeParam("hostName") java.lang.String hostName,
         @ProbeParam("serverName") java.lang.String serverName,
         @ProbeParam("serverPort") int serverPort,
         @ProbeParam("contextPath") java.lang.String contextPath,
         @ProbeParam("servletPath") java.lang.String servletPath) {
        long threadId = Thread.currentThread().getId();
        //if the request is not for my app, then ignore the event
        if (!s.equals("com.sun.samples.probe-app_3.0.0.SNAPSHOT"))
            return;
        System.out.println("requestStarted for app: " + s + " , ThreadID = " + threadId);
        requestMap.put(threadId, new Date().getTime());
    }

    @ProbeListener("glassfish:web:http-service:requestEndEvent")
    public void requestEnd(
            @ProbeParam("appName") String s,
            @ProbeParam("hostName") java.lang.String hostName,
            @ProbeParam("serverName") java.lang.String serverName,
            @ProbeParam("serverPort") int serverPort,
            @ProbeParam("contextPath") java.lang.String contextPath,
            @ProbeParam("servletPath") java.lang.String servletPath,
            @ProbeParam("statusCode") int statusCode) {
        long threadId = Thread.currentThread().getId();
        //if the request is not for my app, then ignore the event
        if (!s.equals("com.sun.samples.probe-app_3.0.0.SNAPSHOT"))
            return;
        System.out.println("requestEnded for app: " + s + " , ThreadID = " + threadId);
        Object startTimeObj = requestMap.get(threadId);
        if (startTimeObj == null) {
            //No start recorded. Just discard the event
            return;
        }
        long totalTime = new Date().getTime() - requestMap.get(threadId);
        requestMap.remove(threadId);
        System.out.println("totalTime taken for app: " + s + " , ThreadID = " +
                            threadId + " : " + totalTime);
        averageRequestTime.setCurrent(totalTime);
}

We were listening to the HTTP service's requestStartEvent and requestEndEvent's and then mapping them together with the currentThread's id, to calculate the total time taken to serve a request for our app. As you see we were able to listen to probes emitted by some other GlassFish component and effectively collect the important statistics. This approach can be used to do a callflow like functionality, to determine the time taken in different containers for each request to your app (eg., JRuby, ejb-container, web-container, jdbc etc.,). This is quite a powerful feature.

Once you have your StatsProvider, you will need to register it with the Monitoring Infrastructure. This is explained here in my earlier blog.

Since you dont have any ProbeProviders for this App, you dont need to make an OSGI bundle for this App. You just need to deploy it normally.

By just using the StatsProviderManager API to register your StatsProvider, Monitoring Infrastructure will magically expose your data to various clients.

asadmin client

Following screenshot shows how to view the statistics that you are exposing from your app.
  1. To start with the monitoring is turned off by default. So, any attempt to view them will result in no stats.
  2. Since you tied your statistics object to the 'web-container' configuration, you will need to turn the monitoring for 'web-container' to ON.
  3. When you try to do 'asadmin get -m "\*"|grep myapp', this will show the statistics that are exposed by your app.
  4. Try accessing the App 'curl http://localhost:8080/prober/" a couple of times and you will see your stats getting updated.
asadmin client

RESTful client

Access the URL from the browser and you will see the same statistics using REST.

REST

JConsole

The same statistics can be seen in JConsole as follows.

jconsole
Comments:

Thanks for sharing such vast information. I think GlassFish v3 is the next-Generation Application Server. I am going to attend Sun Tech Days 2010 conference in Hyderabad which would have sessions on GlassFish v3 and other topics such as Java EE platform. Experts are going to share ideas on new technologies there. lets see what happens.

Posted by sharmabhabho on February 18, 2010 at 07:10 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

bloggerprashanth

Search

Categories
Archives
« September 2015
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today