Version 27

    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