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 was developed primarily for monitoring J2EE applications, however JAMon 1.0/2.0 can be used in any JDK 1.2 or higher environment, and JAMon 2.1 can be used in any JDK 1.4 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, WebSphere…), and can also be used in other programming environments that can call Java code (ColdFusion, PowerBuilder, BroadVision, ...). JAMon is particularly useful in multithreaded software like a database engine. Feel free to continue reading the user's guide or download JAMon and read the Java Docs. Note: The FormattedDataSet API generates dynamic text including HTML and XML. It uses JAMon extensively to monitor performance including all JDBC calls. The FormattedDataSet is a powerful open source API in its own right and is also a great primer in using JAMon. Click this link to learn more about the FormattedDataSet. Note: Possible WebSphere issue with jamonadmin.jsp. |
1. What's new in JAMon 2.7? HTTP and EJB Monitoring |
JAMon 2.7 introduces the ability to monitor HTTP requests in web containers such as Tomcat, JBoss, and Jetty. This monitoring is achieved with no code changes required by developers. See HTTP Monitoring with JAMon for more information. JAMon 2.7 also introduces EJB monitoring. Any EJB3 methods as well as any exceptions they throw will be monitored. The information can be viewed in /jamon/jamonadmin.jsp. EJB requires no coding changes to your EJBs. Simply follow these steps to enable the EJB interceptor on your app server:
<?xml version="1.0" encoding="UTF-8"?>
|
2. What's new in JAMon 2.2 and 2.3? |
JAMon 2.3 fixes a few bugs
JAMon 2.2 fixes a few bugs and adds the new JAMon JDBC driver which allows developers to monitor JDBC/SQL without changing any code. The JAMonDriver class is com.jamonapi.proxy.JAMonDriver and representative URLS follow. Note in the jamonrealdriver below the actual driver is used.
JDBC Syntax Without JAMon: An example of how to connect to a database using a JDBC driver follows (The example uses Sybase, but any vendors driver would do)
JDBC Syntax With JAMon: The following code will use JAMon as a proxy to track performance, but uses the underlying driver to perform the queris
(The example uses Sybase, but any vendors driver would do). Note no code changes would be required if connection strings were placed in a configuration
file. The JAMon jar file must also be placed in the classpath.
Note JAMon simply removes 'jamon', and 'jamonrealdriver=XXXX' from the url, so the url should work with the underlying driver when they are removed. Note the '?' above is not part of JAMon syntax, but instead part of the underlying Sybase driver syntax. In the Oracle example below, there is no delimiter between 'jamonreaddriver' and the previous part of the oracle driver, which looks odd, but it is appropriate.
Bug Fixes:
|
3. What's new in JAMon 2.1? |
JAMon 2.1 introduces two easy to use, but powerful new capabilities:
JAMon can be enabled/disabled at runtime. If it is disabled then the original object is simply returned, causing no run time monitoring performance. Having said that the monitoring is quite fast and can be enabled in most production systems. This version of JAMon requires JDK 1.4 or higher. Previous versions were JDK 1.2 or higher. |
3.a Monitoring Interfaces |
With one line of code you can monitor ANY java interface. Any interface means you can easily monitor standard java interfaces such as JDBC, open source interfaces such as the log4J appender interface or your own custom interfaces. To monitor an interface you simply have to call the following JAMon method:
That's it! Simply make method calls to myObject as you normally would, and the calls will be monitored. (Note it is best to hide the use of JAMon in a monitoring class of your own creation). |
3.b Monitoring Interfaces - Method Calls (JAMon Summary Statistics) |
JAMon summary statistics such as hits, time statistics (avg,total,min,max), concurrency statistics and more will be tracked for all of methods of the interface. The JAMon label for monitoring of interface method calls always begins with: MonProxy-Interface. JAMon statistics are viewable via the jamonadmin.jsp page in jamon.war (discussed later). The following is an example of the JAMon label associated with the Connection classes close() method. Note the JAMon label consists of the concrete class as well as the interfaces method signature. MonProxy-Interface (class=org.hsqldb.jdbcConnection): public abstract void java.sql.Connection.close() throws java.sql.SQLException Interface summary statistics are viewable via jamonadmin.jsp. Click this link to see MonProxy-Interface data from the live demo. |
3.c Monitoring Interfaces - Exceptions (JAMon Summary Statistics) |
JAMon summary statistics are kept whenever a monitored interface throws an Exception. Any time a monitored interface throws an exception several JAMon summary records will be added. JAMon labels for Exception summary statistics begin with: MonProxy-Exception. These summary statistics allow developers to easily see how many Exceptions the application has thrown. For each exception that the interface throws the the following three types of JAMon summary labels will appear in the report.
Exception summary statistics are viewable via jamonadmin.jsp. Click this link to see MonProxy-Exception data from the live demo. |
3.d Monitoring Interfaces - Exceptions (Exception Details) |
The details of the N most recent Exceptions thrown by monitored interfaces (including the stack trace) are kept in a rolling buffer and viewable via exceptions.jsp. The exception buffer size is configurable via the web page, and defaults to the most recent 50 exceptions. Typically such stack trace information is only available in a log which a developer might not have access to and even if they do the log must be parsed to view the stack traces. Each row in the report represents a recent Exception thrown from a monitored inteface. Each row contains the following columns
Exception details statistics are viewable via exceptions.jsp. Click this link to see Exception Details data from the live demo. |
3.e Monitoring Interfaces - Note on Exception Monitoring |
One nice thing about Exception monitoring is that even when developers gobble/hide exceptions in the following manner they will show up in the JAMonAdmin report and exception detail report. The following example is taken from the JAMon demo. // Throw an exception and show that it is also monitored in jamonadmin.jsp and exceptions.jsp // Note also even though the catch block is empty it will show up in these pages. try { // get a query to throw an Exception. If enabled will show in jamon report and sql details. st.executeQuery("select * from i_do_not_exist"); } catch (Exception e) {} |
3.f Monitoring Interfaces - JDBC Interfaces |
JDBC interface monitoring has all the capabilities mentioned above, but also a few extras.
|
3.g Monitoring SQL Commands |
One of the most powerful aspects of JAMon 2.1 is that it can track performance for all queries issued by an application (see 'Monitoring SQL Commands - JAMon Summary Statistics') and allow developers to view all recent queries that have executed in a rolling buffer (see 'Monitoring SQL Commands - Details'). |
3.h Monitoring SQL Commands (JAMon Summary Statistics) |
A number of different JAMon summary statistics will be kept for each query executed from a monitored Statement/PreparedStatement/CallableStatement. JAMon labels for SQL summary statistics begin with: MonProxy-SQL. These summary statistics allow developers to see how many times a query has been executed, what its time statistics are (avg/total/min/max/...), whether or not it is currently executing and if so how many times, and more. For each SQL command the following JAMon summary labels will appear in the JAMonAdmin report.
|
3.i Monitoring SQL Commands (SQL Details) |
The details of the most recent N SQL commands issued are kept in a rolling buffer and are viewable via sql.jsp. The SQL buffer size is configurable via the web page, and defaults to the most recent 100 queries. Each row in the report represents a recently executed SQL command. By default the report is sorted with the most recent queries showing at the top. Each row contains the following columns
SQL details are viewable via sql.jsp. Click this link to see SQL Details data from the live demo. |
3.j Live Demo |
A live demo is available on the web that demonstrates Interface/JDBC/SQL monitoring. It can be run at http://www.ssouza.com/jamon. From this menu the following pages can be executed. The live demo is also the application that you will use to view JAMon stats in your own environment. Simply install jamon.war and place the jamon jar file in your servers class path (Note it should be put in your servers class path so you can monitor other apps).
|
3.k JAMon 2.1 Miscellaneous |
|
4. What's new in JAMon 2.0? |
The following subsections describe JAMon 2.0, and how it can be used to improve your programs. |
4.a What is JAMon 2.0? |
JAMon 2.0 can be thought of as an in-memory aggregate database. Most databases store the details (rows) and these details can be aggregated/summarized by writing SQL (using the ‘group by’ clause). JAMon takes the approach of throwing out the details and keeping the aggregates. This allows JAMon to be very fast and have a small memory footprint. |
4.b Aggregation is Information/Details are Noise |
Often people make decisions based on summary information (aggregates) and not detailed information. Imagine trying to figure out the performance of a particular query by looking through a multi-gigabyte log file searching for the occurences of the query (buried among other log details). Trying to understand this data would be impossible without aggregation. Using aggregates such as averages, mins and maxes would be much more useful to see if the query needed to be tuned. This concept of aggregating statistics is the basis of Decision Support Systems (DSS). JAMon 2.0 allows you to easily aggregate ANYTHING that happens in your application. |
4.c JAMon 1.0 - Good |
JAMon 1.0 only tracked aggregate statistics for time (the units were in milliseconds/ms.). For example,
if the following code was called 10 times: Representative performance statistics may look like this: 10 hits, average=100 milliseconds (ms.), total=1000 ms., minimum=50 ms., maximum=200 ms. This is very useful, but there are many things it would be useful to aggregate that are not time based (i.e. money, MB, locks, rows, …) |
4.d JAMon 2.0 - Better |
In JAMon 2.0 the concept of aggregating a time associated with a String has been expanded to aggregate any number associated with any arbitrary key. The key can consist of any number of Objects. Here are some examples of possible JAMon 2.0 keys:
This is a simple, but powerful concept that allows developers to expose many things that are happening inside their applications. Because JAMon is easy to use and fast, developers can now unleash the power of aggregation to improve their programs in many new, innovative ways. Start aggregating! |
4.e What else is JAMon? |
Here are ways that I think of JAMon that helps me uncover ways to use it. JAMon is...
|
4.f How can I use JAMon? |
Here are a few of the many uses of JAMon.
Note: Querying JAMon statistics - Between JAMon’s API for extracting the aggregate data, and the FormattedDataSet’s ArraySQL class which allows you to query the JAMon statistics in a SQL like manner, your programs can easily take action based on JAMon data. |
4.g Specific examples may help you understand the possibilities |
The simple syntax below demonstrates how easy it is to aggregate statistics for purchases (the units are in dollars). The number ($123.40) represents the dollar value of the individual purchase: MonitorFactory.add(“purchases”, “$”, 123.4); If the code above was called every time a purchase was made (with 123.4 replaced by a variable) then the JAMon report would be able to show business users and developers, statistics on total purchases in real time. Using JAMon is that easy! Here are some other ideas for things to monitor in JAMon 2.0:
The following measurements/numbers can only be tracked in JAMon 2.0. Strings and numbers in the examples below are hard coded, but variables can just as easily used:
In general you can track any numbers! A list of other ideas follows:
Other numbers you could summarize: quantity, percentage, count, total, min, max, grade, score, rating, rank, price, cost,… |
4.h How do I use the new MonitorFacatory.add(...) method? |
Here is an example of how you could use the new MonitorFactory.add(...) method to perform the functionality of JAMon 1.0's start/stop timer. In fact this is more or less the way this capability is implemented in JAMon 2.0. The first example does not allow you to tell if the code being monitored is currently running (i.e. active), whereas the second example would. Example 3) is the proper way to do timed monitors, the other examples are merely demonstrative.
|
4.i What other improvements were made in JAMon 2.0? |
|
4.j Incompatibilities with JAMon 1.0 |
Due to the fact that JAMon 2.0 was a significant rewrite, quite a few (the majority) of JAMon 1.0's classes are no longer there, and the methods of some classes have changed. If you just use start()/stop() and jamonadmin.jsp this won't affect you. In general it is a good idea to hide calls to JAMon (or any other 3rd party software) in classes that you own. What follows is a list of some of the major changes:
|
4.k JAMon challenge #1! Your Help is needed! |
I would like to incorporate JAMon into other open source projects. Often this can be done very quickly. I recommend hiding JAMon behind a class of the specific projects owning. This allows the program to work even if JAMon is not available at runtime. HSQLDB used this approach JAMon has already been incorporated into HSQLDB, Fulcrum, and the Spring framework. There are many other projects that would benefit from JAMon stats such as JBoss, JDBC drivers, Struts, and TomCat. I will gladly assist in incorporating JAMon into your project. |
4.l JAMon challenge #2! Your Help is needed! |
The most important aspect of JAMon is not the current Java implementation, but the concept of aggregating ANY number associated with ANY key using ANY language in ANY program on ANY platform. The JAMon code is simple enough to implement in many languages. I would like to see JAMon coded in C++, C##, Perl, Ruby and more. I would even love to see JAMon-like aggregate stats at the operating system level! There could be various levels of compliance. The simplest one could be done in a matter of hours in just about any language (I have sample sample code for this if you would like to see it). Here are the levels of compliance:
I will gladly assist anyone wishing to port JAMon to another language. This would be a great college project! |
5. Advantages of JAMon |
Using JAMon is easy. Place the jamon jar file (80K) 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 how 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 550,000 times per second. After disabling, the methods execute 15,000,000 times per second. To test JAMon's performance download the 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, memory consumption, locks used, database connections consumed,... . JAMon's start(), and add() methods take a string/label 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, 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: |
|
6. The JAMon servlet filter - Begin monitoring in 5 minutes! |
A Servlet filters is a simple piece of Java code that is executed whenever a Java Web Application resource is accessed. Resources include Servlets, JSP's, GIFs, JPeg's, and HTML documents. The simple filter example will monitor all of these. By using JAMon the filter becomes a powerful web site hit counter. Statistics for pages will be gathered such as hits, and execution time (avg, min, max). In addition you can see which pages are currently executing. The JAMon servlet filter does not require ANY code changes. You simply put jamon's jar file in your servers classpath, put the following entry into your web.xml file, and install the JAMon war so you can view your statistics. Note you can choose what types of pages you would like to monitor by altering the 'url-pattern' element below. See Java documentation for more info on how servlet filters work. Note: The order of entries of your web.xml files is important.
|
7.a The JAMon Web Application (WAR) - Viewing JAMon stats via jsmonadmin.jsp |
JAMon comes with the jamon.war web application (Web Application Archive). This application contains jamonadmin.jsp, which enables you to view/query the JAMon statistics via a sortable HTML report, XML or an Excel spreadsheet. To view JAMon statistics you must put the jamon jar file in your server's classpath (In Tomcat you can put the jamon jar file in common/lib), and install jamon.war. If your own application uses the JAMon servlet filter you will be able to view the statistics by running jamonadmin.jsp (http://host:port/jamon/jamonadmin.jsp). |
8. JAMon Examples |
8.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.
|
8.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: |
|
9. 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. |
9.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: |
|
9.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)". |
|
9.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: |
|
10. 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. To Assist Testsers in the Test/QA process - This link describes how JAMon can be used in the testing process. |
11. 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. Porting JAMon to other languages and putting JAMon into other open source programs would also be interesting future initiatives |
12. 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. |
13. Downloading JAMon |
Click here to download JAMon. This download contains:
|
14. Support |
Please submit any questions about JAMon to the sourceforge support forum, so that all users may benefit from the answers. The following link will take you to the JAMon support forum JAMon Support Forum. If JAMon has been helpful please make a donation to help offset the costs of running the project: Donate to JAMon |
15. JAMon/FormattedDataSet T-shirts |
Note: I have been happy with the JAMon shirts I own, but buy at your own risk. Should you have any problems with the product please contact Zazzle directly.
In case the flash application does not display properly, you may also purchase T-Shirts via this link: JAMon T-Shirts |
JAMon has a very liberal license agreement. The spirit of the license is that there are no restrictions on its use. Should something not be clear in the license feel free to contact me, and I can clarify. In general JAMon binaries can be used free of charge in any software (commercial software too), and JAMon source code may be modified (any modifications must be noted per the license agreement). 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.
I am indebted to the following for their support in improving JAMon.
- Ed Desrosiers - A coworker of 15 years that was involved in the early design of JAMon. I also often use him as a sounding board for ideas I have (he sat 5 feet from me in this cubicle based world). In addition he came up with the idea of 'Last Value' in JAMon 2.0., and comes up with inventive ways to use JAMon and the FormattedDataSet.
- Eric Laufer - Helped make the JAMon and FormattedDataSet screens look more professional.
- Ron Weinstein - Another Sybase coworker that served as a sounding board. His input in JAMon 2.0 helped improve JAMon ranges.
- Peter Blagrove - A college friend that is a great sounding board for ideas.
- Jeroen Borgers - Jeroen suggested internationalizing dates and numbers in the JAMon 2.0 reports.
- Jack Shirazi - Jack runs a great Java Performance Tuning website. He saw the value of JAMon right away and hosted it during the initial release.
- Java Ranch - I am a regular contributor to the excellent Java Ranch performance tuning forum. If you haven't checked out Java Ranch yet, I suggest you do as a lot of smart people post there. Here is a performance FAQ/rant that summarizes most of my thoughts on performance tuning. Java Ranch has also given me a venue to promote JAMon.
- Your name! - Your contribution! See the JAMon Challenges section!
Steve Souza has 20+ years of software and database development experience specializing in performance tuning.
Document last modified 07/2011.