Collecting Method Invocation And SQL Statistics Per Transaction
The service is available since JBoss-3.2.4RC2 in module varia.
(in jboss-head, moved to contrib/varia.)
Description
This service tracks method invocations and/or SQL statements executed in a transaction and
allows to print different reports in HTML with statistical information.
The transaction is identified by (or given a name of) a method name that started this
transaction.
For example, if a transaction is started by invoking a method create
of a session bean home interface org.spec.jappserver.orders.orderses.ejb.OrderSesHome
then the transaction will be given the following name
org.spec.jappserver.orders.orderses.ejb.OrderSesHome.create.
The service will track each method (including calls to other EJBs through their local, remote, home and local home interfaces) and SQL statement
executed in this transaction.
During the run of your application, this transaction might be executed more than once. In this
case, the service will count the number of times the transaction was executed during the
application run.
Note, the statistics are collected only for successfully committed transactions. If a transaction was rolled back its statistics are lost.
Reports
To generate reports, go to JMX console
and click on the service name (the default name is jboss.stats:service=StatisticsCollector)
to open the JMX MBean view. On the view page invoke the operation reports.
As the result, you will see a list of available reports by titles. Choose the one you are interested in.
Reports are generated by report generators. Each report generator is an MBean that extends abstract class org.jboss.varia.stats.report.ReportGenerator. You can implement and deploy your own report generators. At the moment, there are two report generators available: table statistics report which shows SELECT, UPDATE, INSERT and DELETE statistics per table per transaction with the exect SQL statements executed and a general report which consists of both method invocation and SQL statement statistics per transaction.
General Statistics Report
General statistics report lists transactions with the number of times they were executed in the run. Choosing a transaction from the list by clicking on its name will display method invocations and SQL statements executed in the chosen transaction. The last item in the list is 'all transactions'. This is the default item which displays all the method invocations and SQL statements executed in the run.
The report consists of two tables: one is for method invocations, the other one is for SQL statements. Each method invocation and SQL statement are the statistical items and treated the same, i.e. display rules for both are the same. Each of the two tables lists various statistical items that took place (for methods it's invocation, for SQL statements it's execution) in the chosen transaction featuring:
item name (method name or SQL statement)
percentage of transactions the item took place in
average number of times the item took place in this transaction (since, this transaction might be executed several times in the run, the average number is calculated by summarizing the number of times the item took place in each transaction and dividing by the number of times the transaction was executed in the run)
the minimum number of times this item took place in the transaction
the maximum number of times this item took place in the transaction
Note, avg might not equal (min + max)/2 in this case.
Table Statistics Report
This report consists of statistical information for SELECT, UPDATE, INSERT and DELETE SQL statements executed against each table in concrete transaction or all the transactions. You can choose the concrete transaction or 'all transactions' item from the transaction list.
The report consists of three tables: the first is a list-menu of transaction titles, the second one contains the total number of SELECT, UPDATE, INSERT and DELETE operations (as columns) executed against each table (as rows), the third table lists the exact SQL statements executed in the chosen transaction.
Deployment
The classes can be found in the statscollector.jar in the varia module. This JAR
file should be copied to the server's lib directory (e.g. server/default/lib).
The service configuration file is called statscollector-service.xml and
can also be found in the varia module. This file should be copied to the server's deploy
directory.
Configuration
There are at least two items to configure: the datasource and the EJB container.
EJB Container Configuration
The configuration of an EJB container consists in adding one interceptor to the container's
interceptor stack. For example, for an entity bean the stack can be:
<container-interceptors> <interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.TxInterceptorCMT</interceptor> <interceptor service="jboss.stats:service=StatisticsCollector"> org.jboss.varia.stats.TxStatisticsInterceptor </interceptor> <interceptor>org.jboss.ejb.plugins.EntityCreationInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.EntityInstanceInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.EntityReentranceInterceptor</interceptor> <interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.EntitySynchronizationInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.cmp.jdbc2.RelationInterceptor</interceptor> </container-interceptors>
The interceptor added is the org.jboss.varia.stats.TxStatisticsInterceptor. Note,
it should follow the org.jboss.ejb.plugins.TxInterceptorCMT.
The service attribute should contain the name of the StatisticsCollector
service to which this interceptor will report.
An example of a session bean interceptor stack:
<container-interceptors> <interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor> <interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor> <!-- CMT --> <interceptor transaction="Container">org.jboss.ejb.plugins.TxInterceptorCMT</interceptor> <interceptor transaction="Container" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor> <interceptor transaction="Container">org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor</interceptor> <!-- BMT --> <interceptor transaction="Bean">org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor</interceptor> <interceptor transaction="Bean">org.jboss.ejb.plugins.TxInterceptorBMT</interceptor> <interceptor transaction="Bean" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor> <interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor> <interceptor service="jboss.stats:service=StatisticsCollector"> org.jboss.varia.stats.TxStatisticsInterceptor </interceptor> </container-interceptors>
DataSource Configuration
Collecting SQL statistics is optional. If you are interested only in method statistics
per transaction, it is enough to configure the EJB container.
However, if you are also interested in SQL statistics, you have to configure the DataSource.
To track the SQL statements executed in a transaction we need to intercept the calls to either
the driver or the DataSource that execute the statements. This implementation uses the former
approach. I.e. there is a service (which is called DataSourceInterceptor) which
implements the javax.sql.DataSource interface and bound into the JNDI.
This service delegates all javax.sql.DataSource method invocations to the target
DataSource, i.e. the DataSource it wrapps. The application should use this DataSourceInterceptor
instead of its target DataSource (the one that is wrapped by this DataSourceInterceptor service) directly.
The configuration of the DataSourceInterceptor service can be found in the
statscollector-service.xml. Here it is:
<!-- DataSource interceptor service --> <mbean code="org.jboss.varia.stats.DataSourceInterceptor" name="jboss.stats:service=DataSourceInterceptor"> <!-- the service this interceptor reports to --> <depends optional-attribute-name="StatsCollector">jboss.stats:service=StatisticsCollector</depends> <!-- JNDI name under which the service will be bound. --> <attribute name="BindName">java:/DSInterceptor</attribute> <!-- JNDI name of the target DataSource --> <attribute name="TargetName">java:/DefaultDS</attribute> <depends>jboss.jca:service=LocalTxCM,name=DefaultDS</depends> </mbean>
In JBoss Application Server 4.2.3 and JBoss Application Server 5.0 the class has been renamed depending on JDBC3 or JDBC4 support
<!-- DataSource interceptor service: use JDK5 for JDBC3 and JDK6 for JDBC4 --> <mbean code="org.jboss.varia.stats.DataSourceInterceptorJDK5" name="jboss.stats:service=DataSourceInterceptor"> <!-- the service this interceptor reports to --> <depends optional-attribute-name="StatsCollector">jboss.stats:service=StatisticsCollector</depends> <!-- JNDI name under which the service will be bound. --> <attribute name="BindName">java:/DSInterceptor</attribute> <!-- JNDI name of the target DataSource --> <attribute name="TargetName">java:/DefaultDS</attribute> <depends>jboss.jca:service=LocalTxCM,name=DefaultDS</depends> </mbean>
The service depends on the StatisticsCollector service to which it
will report SQL statements executed.
The BindName is the name under which this service will be bound in the JNDI.
And this is the name your application should use (e.g. entity beans should use this name
as the DataSource name).
The TargetName is the JNDI name of the target (wrapped by this service) DataSource.
Cache contention/eviction/hit/miss statistics for "cmp2.x jdbc2 pm"-based containers
The statscollector-service.xml by default deploys cache statistics report generator. But the generator itself doesn't collect the statistics. For each entity you want to collect the cache statistics for you should deploy a cache listener that will do the job. Here is an example:
<server> <mbean code="org.jboss.varia.stats.CacheListener" name="jboss.stats:service=cachelistener,ejbname=AssemblyEnt,table=M_PARTS"> <!-- the service this interceptor is reporting to --> <depends optional-attribute-name="StatsCollector">jboss.stats:service=StatisticsCollector</depends> <!-- the cache service this interceptor is listening to --> <depends optional-attribute-name="CacheName">jboss.cmp:ejbname=AssemblyEnt,service=tablecache,table=M_PARTS</depends> </mbean>
This cache listener will collect cache contention, eviction, hit and miss events for entity AssemblyEnt mapped to table M_PARTS.
ToDo
If you like the idea you are welcome to contribute. Here are some tasks.
the generation of HTML reports is hardcoded into the report generators (MBean's). It would be nice to externalize it in some way and make it nicer
filtering of transactions, i.e. do not collect statistics or collect statistics only for given transactions
filtering tables and SQL operations, i.e. collect or do not collect statistics for INSERT and DELETE operations for specific tables
sorting the tables by on click
you name it
outofmemory, so clear the cache on heavy load
fix TxStatisticsInterceptor for EJB3. EJB3 uses JBoss-AOP
Comments