Chapter 7. Metrics and Statistics

In this chapter, we will demonstrate how to produce statistical data points and collect metrics. Hibernate can be configured to start collecting and producing this data. Additionally, we will see how it can be collected through Java Management Extension (JMX). We will be covering the following topics in detail:

  • Statistical data types:
    • Session
    • Entity
    • Collection
    • Query
    • Cache
  • Statistics via JMX:
    • An introduction to JMX
  • Using JMX with Hibernate

Statistical data types

Hibernate collects various data points to help you measure the usage and performance of your application. This includes data collected about the session, entities, collections, query, and cache. Here, we discuss how to obtain this data and what each set of data points means.

To instruct Hibernate to collect metrics, you first need to enable the generation of statistical data. You have already seen how this is done in Chapter 5, Hibernate Cache but, just in case you skipped ahead, all you need to do is add the following property to the session factory configuration:

<property name="hibernate.generate_statistics">true</property>        

Hibernate will then start collecting data points, however, be aware that this could slightly impact the performance of your application, since it now has to do more work. Later, we can see how you can enable and disable statistics data generation using JMX. You can also clear the statistics data and start over. For now, let's see what we can collect and how that is done.

Session

When you enable statistics, Hibernate collects very useful data points about your interaction with the data store. Here is a list of some of the metrics to give you an idea of what is available. You can gather data from the session factory object. For a complete list of objects, refer to the JavaDoc for SessionFactory.

Name

Purpose

Start time

This returns the session's start time. The returned value is a long value, which you can pass to the Date() constructor to create a date object; for example:

Statistics stats =
         sessionFactory.getStatistics();
Date startTime = new Date(stats.getStartTime());
System.out.println("started on: " + startTime);

Connection count

This returns the total count of all the JDBC connections made for this session factory.

Session count

This returns the total count of all sessions that were opened and closed in this session factory. There are two methods, one to obtain the open count and another for the closed count.

Entity load count

This is the total number of entities loaded by all the sessions created by this session factory.

Entity fetch count

This is the total number of lazy associated entities that were initialized because they were referenced.

Entity insert count

This is the total number of entities inserted using this session factory.

Entity delete count

This is the total number of deletions that occurred in this session factory.

Entity names

These are the entity names that were loaded in this session factory. This is useful for obtaining entity statistics by name. (Refer to the following Entity section.)

Collection names

These are the attribute names of the associated collections that were fetched in this session factory. This is useful for obtaining collection statistics by name. (Refer to the following Collection section.)

Query names

These are the attribute names of the queries executed in this session factory. This is useful for obtaining query statistics by name. (Refer to the following Query section on query statistics).

Second-level cache region names

These are the names of all the second-level cache regions used by this session factory. We saw this in Chapter 5, Hibernate Cache.

Additionally, when you enable Hibernate statistics, you will start seeing session statistics in your log appender every time a session is closed. This message contains a lot of information about each session:

INFO org.hibernate.engine.internal.StatisticalLoggingSessionEventListener:275 - Session Metrics {
    6498 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    911975 nanoseconds spent preparing 22 JDBC statements;
    9793980 nanoseconds spent executing 22 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    3812324 nanoseconds spent performing 70 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    140801 nanoseconds spent performing 1 L2C misses;
    1756437 nanoseconds spent executing 1 flushes (flushing a total of 69 entities and 21 collections);
    65969 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

If that is not desired, and you still wish to collect statistics without filling your log files, you can stop this by adding an entry in your logger configuration. For example, in the case of log4j, add the following entry:

log4j.logger.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=OFF

Next, we'll discuss which metrics are available for entities.

Entity

In addition to the metrics you can collect about sessions, you can further collect stats for one particular entity. Note that the name of the entity is the fully qualified name, which includes the package name. You can also get the names of all entities from the session statistics, as discussed in the last section. Let's have a look at the following example:

String[] entityNames = stats.getEntityNames();
for(String entityName: entityNames) {
  System.out.println("entity name: " + entityName);
  EntityStatistics es = stats.getEntityStatistics(entityName);
  System.out.println("Delete: " + es.getDeleteCount());
  System.out.println("Insert: " + es.getInsertCount());
  System.out.println("Update: " + es.getUpdateCount());
  System.out.println("Load: " + es.getLoadCount());
  System.out.println("Fetch: " + es.getFetchCount());
}

Note

As indicated earlier, when reading statistics, the difference between load and fetch is that load indicates that the entity is fully loaded from the database, and fetch indicates that the entity was loaded previously in an uninitialized state, but it's now being fetched from the database to be initialized.

Hibernate returns an uninitialized object in two cases: first, if the entity is an associated entity of a parent class whose fetch mode is set to lazy, second if an entity is requested from the session via the load method. The difference between session.get() and session.load() is that get initializes the entity by hitting the database, whereas the load method returns an uninitialized proxy object and it is only initialized when the entity properties are accessed. (We covered proxy objects in Chapter 1, Entity and Session).

Collection

Similar to entity statistics, you can obtain further metrics about collections. Likewise, you need to get this data by referring to the collection statistics by their role name.

Query

Query statistics produce some very good metrics. This is probably the most useful data for monitoring query execution and identifying the bottlenecks. The following table shows the metrics for each query. Similar to entity and collection statistics, you'll have to obtain the query statistics by name:

Name

Purpose

Execution count

This is the number of times a query is executed.

Execution average, max, and min time

This is the maximum, minimum, and average time spent executing this query.

Execution row count

This is the total number of rows returned by executing this query since application started.

Cache put, hit, and miss count

The number of times this query added entities to cache, or read from cache, or missed when reading from cache.

Cache

We have already covered collecting cache statistics in Chapter 5, Hibernate Cache. The only thing that is noteworthy to add here is related to query statistics, discussed in the last section. It is important to note that, in order for a query to interact with cache, you need to set it to cacheable. So, if you expect cache hits in your query statistics, but don't find any, it's most likely that the query is not set to cacheable. In the following example the query is set to cacheable:

Query query = session.createQuery("from Person")
     .setCacheable(true);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.226.120