|
|
|
First Published June 2002; Updated October 2002
TABLE OF CONTENTS |
---|
1. JAMon Introduction |
---|
The Java Application Monitor (JAMon) is a free, simple, high performance, thread safe, Java API that allows developers to easily monitor production applications. JAMon can be used to determine application performance bottlenecks, user/application interactions, and application scalability. JAMon gathers summary statistics such as hits, execution times (total, average, minimum, maximum, standard deviation), and simultaneous application requests. JAMon statistics are displayed in the sortable JAMon report. Click JAMon report to see a live demo of JAMon.
JAMon was developed primarily for monitoring J2EE applications, however it can be used in any JDK 1.2 or higher environment. JAMon can be used in Servlets, JSP's, EJB's and Java Beans in various J2EE Application Servers (Sybase's EAServer, and BEA's WebLogic,?), and can also be used in other programming environments that can call Java code (ColdFusion, PowerBuilder, BroadVision, ...). |
2. Advantages of JAMon |
Using JAMon is easy. Place JAMon.jar (90K) in your classpath, and surround the code that you wish to monitor with the JAMon API's start() and stop() methods. See the code sample below:
|
|
For example, to collect statistics for all JSP pages in a Web Application, a developer would place a call to the start() method at the top of every JSP, and a call to the stop() method at the bottom. With a few minutes work the developer will have statistics for all application pages. The statistics will include number of page hits, average page execution times, and the number of users simultaneously accessing each page. The statistics can be displayed as an HTML table by calling the getReport() method, or using JAMonAdmin.jsp.
JAMon requires no special administration accounts. Many monitoring tools require administrative accounts to install monitoring software, and to view statistics. Due to the complexity of these tools, developers typically go through specially trained administrators to access monitoring statistics. Many of these monitoring tools also require holes punched in firewalls.
JAMon has none of these problems. Statistics gathered via JAMon are available to all developers via JAMonAdmin.jsp. No administrative accounts, rights, or set-up are required for gathering and viewing statistics. Because the JAMon API is part of the application code, developers can switch J2EE App Servers and monitoring will continue to work. JAMonAdmin.jsp is accessed via HTTP and so can be viewed without punching any additional holes in firewalls.
JAMon can be used to monitor production systems. Monitoring production systems is important because it is the only way we can see the frequency that our code is being executed by real users. Also, many times the configuration of the production environment is different from the test environment, so the performance numbers between the two environments may be considerably different. For both these reasons monitoring only the test environment is not enough.
Unlike many monitoring tools, JAMon, due to its minimal performance overhead and multi-threaded capabilities, can be used in production systems. JAMon can be disabled at runtime (using JAMonAdmin.jsp), further reducing performance overhead. On a 2 Ghz Pentium IV, JAMon's start(), and stop() methods execute 500,000 times per second. After disabling, the methods execute 30,000,000 times per second.
To test JAMon's performance download JAMon.jar and execute the following command. The number represents how many times start(), and stop() should be called in the various tests (100,000 will be used as the default if a number is not provided).
The last label ("Full Factory TimingMonitor()") in the output indicates how long it takes to run when monitoring is enabled, and the label starting with "NullMonitor2()" indicates how long it takes to run when monitoring is disabled.
JAMon is flexible. Many monitoring tools specialize in monitoring specific parts of an application. This can force a developer to resort to using multiple monitoring tools to cover all of their monitoring needs. For example, a developer may have to use different tools to monitor each of the following: page hits, EJB invocations, method calls and database connections,... .
JAMon's start() method takes a string as an argument. This string can be a JSP page name, an EJB name, a method name or any other code or concept that can be represented by a string.
Also, because strings are passed to the start() method, a developer can decide what to monitor based on runtime data. Using this technique we can monitor trends as well as performance bottlenecks. Some examples of JAMon's flexibility: |
|
3. JAMon Examples |
3.a Simple Example |
JAMon gathers statistics for any code that comes between start() and stop() methods. In our first somewhat artificial example we will be timing how long our program sleeps when calling the Java Thread.sleep() method ten times from within a "for" loop. |
|
MonitorFactory.start("myFirstMonitor") both creates a monitor and begins gathering monitoring statistics. The start() method takes a monitor name/label as an argument. Summary statistics are gathered for all monitors that are passed identical labels. In our example the start() method is called 10 times with the same label, so the summary statistics will include data from all 10 calls.
The next line in the example is the sleep() method. The sleep() method takes one argument, which is the number of milliseconds the active thread should sleep. The loop has the effect of sleeping the thread for 101,102,?,and 110 ms. Finally comes the stop() method which will stop gathering statistics.
After the loop we print the statistics to the console, taking advantage of the monitor's toString() method. Let's take a look at what these statistics mean:
The rest of the line contains summary statistics for the ten monitor calls. Considering our logic timed the sleep method 10 times with values ranging from 101 to 110 ms. the following results seem reasonable.
|
3.b Monitoring a Servlet - Gathering page statistics |
In our second example we will use JAMon to gather page statistics for a servlet. To gather page statistics a developer places a start() at the top of the servlets doGet() or doPost() method, and a stop() in the finally clause. If a method that can throw an exception is being monitored, then the stop() method must be called from the method's finally clause. This ensures that the monitor is stopped when an exception is thrown.
The sample servlet doesn't do much. It simply returns a list of musicians from three legendary reggae groups (Sample Output). The servlet sleeps for three seconds which slows down processing enough to get simultaneous servlet instances running. The getMusicians() method sleeps an amount based on the number of servlet instances currently running. This will help in demonstrating how JAMon can be used to measure application scalability. The statistics generated by this example will be discussed in the next section.
The code for the example follows: |
|
This example demonstrates the flexibility of the JAMon API, by incorporating runtime data such as date and IP address into our monitor labels. We are monitoring the following items in our servlet: |
|
4. Managing JAMon - JAMonAdmin.jsp |
JAMon comes with a JSP that allows developers to view the JAMon report and control JAMon behavior. JAMonAdmin.jsp can be found in the JAMon.war download. |
4.a The JAMon Report |
The JAMon report has one row for each unique monitor label that was passed to the MonitorFactory.start("?") method. This row is called a "JAMon report entry". The JAMon report displays all monitor information in one HTML table. The following statistics were discussed in enough detail in the previous example and won't be covered here: monitor label, hits, average, total, minimum, maximum, first access and last access.
We will be referring to the JAMon report in the following text (note sorting will only work when viewing the JAMon report from JAMonAdmin.jsp).
Looking at "JAMonDemo.pageHits" JAMon report entry we can see that the servlet had 30 page hits taking on average 3,441 ms. Some other statistics that require further discussion follow: |
|
Note the JAMon report in JAMonAdmin.jsp can be sorted by clicking column headers. Clicking will toggle between ascending and descending sorts, based on column values. An up arrow indicates ascending, and a down arrow indicates descending.
The JAMon report can be displayed in a number of different ways. Two of the ways follow: |
|
4.b Measuring outliers (JAMon Time Ranges) |
A problem with the statistics previously mentioned is that they hide extreme data points (i.e., outliers). When application performance degrades we become more interested in outliers. JAMon time ranges contain information about these outliers.
Ideally we would like the average time for a monitor to be close to its minimum. However many factors (such as number of simultaneous users) can cause performance degradation. For example, we would expect our servlet to respond faster with two simultaneous requests than with 5,000.
There are 13 JAMon time ranges. The ranges are measured on an exponential scale. The first range is from 0 to 10 ms., and subsequent ranges double, until the final range, which includes values greater than 20,480 ms. We will use the JAMon report entry "JAMonDemo.getMusicians(Wailers)" and its "81-160ms." time range to discuss the five time range variables. The time range values are "7/114 (1/2.3/7.9)". |
|
4.c Controlling JAMon |
The JAMonAdmin.jsp page also allows a developer to control JAMon at runtime. A description of the function of each of the buttons follows: |
|
5. Ways to use JAMon - More than performance |
This section discusses the various ways JAMon can be used. JAMon's most obvious use is in determining application performance bottlenecks by gathering timing statistics. However, it can also be used in other ways such as determining how users interact with an application, and determining application scalability. Some ways that JAMon can be used follow.
To tune performance - Web applications can be difficult to tune due to the fact that there are many possible bottlenecks including: network IO, database IO, application code, poorly tuned queries, or even an increased amount of site traffic. To help pinpoint problems, performance diagnostics must be built into the application.
Without performance measurements, developers will spend their time guessing where performance bottlenecks occur. Performance problems typically occur in a small percentage of overall code. Algorithm guru Donald Knuth estimated that 4% of application code accounts for 50% of the performance. With measurements, developers can quickly locate that 4% of the code and get the biggest bang for their tuning buck. Without measurements developers waste effort tuning code that may have no significant impact on performance.
To improve code design - "More computing sins are committed in the name of efficiency than for any other single reason-including blind stupidity" - W.A. Wulf "...premature optimization is the root of all evil." - Donald Knuth
Often, when discussing code designs, developers say they don't want to implement certain elegant designs, because of perceived performance problems. JAMon supports the following argument: "Let's code the elegant solution and measure its performance. If it doesn't perform well then we can try the other design."
To determine how users interact with the application - JAMon can be used to answer questions of the following type: |
|
To set coding priorities - Coding priorities can be based on factors such as which features are accessed the most often or what code is the slowest.
To detect programming and user errors - JAMon can be used to track errors, such as when exceptions are thrown, when resources are not released or when a user error occurs such as forgetting a password.
Developers can monitor code that gets and releases a resource, and check to see that the number of hits for both are the same. For example, if we get 1,000 database connections, we should also release 1,000 database connections. MonitorFactory.start("getConnection") would be called when a developer gets a connection and MonitorFactory.start("releaseConnection") would be called when the connection is released. If the hits don't match then we have a resource leak.
Developers can also monitor when Exceptions are thrown or when assertions are triggered. One helpful way to track Exceptions would be by date by user (i.e., "Exception.IllegalArgumentException.05/15/02.jsmith"). This allows developers to determine when exceptions are thrown without depending on users for the information.
To test application scalability - JAMon time ranges correlate performance to application load. Using this information a developer can measure how well an application scales. See the description of JAMon time ranges for more information on how to use JAMon for scalability testing.
To determine what is happening in an application at a snapshot in time - Many monitoring tools monitor an application from the "outside looking in", but because JAMon looks at the application from the inside we can use statistics such as "Active", "First Access" and "Last Access" to determine what activities our application is performing at any given time. |
6. Future Directions |
Currently JAMon does not persist its statistics. When the JVM goes down the statisistics are lost. A future version will be able to persist monitoring statistics to a database. This will allow developers to track how application usage and performance evolves.
Persisting statistics will also allow developers to run monitoring reports that span all tiers of an n-tier application. For example, if we have a clustered application using three web servers, three application servers and one database, we could persist statistics from all these servers into one database. This would allow us to have one report that shows application monitoring statistics for all tiers. |
7. Sample Code |
Java code can be called from both Java and non-Java environments. JAMon can be used in any environment that can call JDK 1.2 code. JAMon has been successfully used in ColdFusion script, BroadVision JavaScript and PowerBuilder. JAMon should also work in Active Server Pages, Java in the database, and many other environments. Sample code follows:
I will continue to add sample code to this document.
|
8. Downloading JAMon |
Click here to download JAMon jar, which contains the JAMon API (approximately 90K). Click here to download all of JAMon (approximately 225K). This download contains:
|
9. JAMon License Agreement |
JAMon has a very liberal license agreement. JAMon binaries can be used free of charge, and JAMon source code may be modified. The JAMon License was adapted from the BSD license. It is requested that any modifications developers make to JAMon be sent to admin@jamonapi.com , so that all JAMon users may benefit.
|
10. About the Author |
Steve Souza is a senior consultant working for Sybase Professional Services in support of the General Services Administration (GSA) in Arlington, VA. He has 20 years of software and database development experience. Please send any questions or comments concerning JAMon to admin@jamonapi.com.
I'd like to thank Ed Desrosiers for his help in designing JAMon, and Eric Laufer for his help in designing the JAMon report and converting this article to HTML. |