Monitor c3p0 in Liferay

The Problem

The c3p0 connection pool exposes MBeans for JMX tools like jconsole to monitor its run-time states. However, both c3p0 and Liferay intentionally generate random MBean names on each startup. The random name of each data source makes it difficult to setup an independent monitoring tool.

The second problem is, by default Liferay creates several data sources, one used by most Liferay features, one for the counter service and one for analytics. They all use the same portal property prefix "jdbc.default.", making them identical in every way except for their random bean names.

The Solution

A default c3p0 bean name looks like this:

com.mchange.v2.c3p0:identityToken=z8kflt9r6r9q5c1rhd86p|5bed8ee2,name=z8kflt9r6r9q5c1rhd86p|5bed8ee2,type=PooledDataSource

The default behavior sets the value of both  identityToken and name to the same random string. According to c3p0 documentation, identityToken can be removed with a system property. The second part of the solution is explicitly name the data sources created by Liferay.

Remove identityToken

Add the following line to TOMCAT_HOME/bin/setenv.sh:

JAVA_OPTS="$JAVA_OPTS -Dcom.mchange.v2.c3p0.management.ExcludeIdentityToken=true"

Explicitly Name Data Sources

Add the following lines to LIFERAY_HOME/portal-ext.properties:

jdbc.default.dataSourceName=liferayDataSource
counter.jdbc.prefix=jdbc.counter.
jdbc.counter.dataSourceName=counterDataSource
jdbc.analytics.dataSourceName=analyticsDataSource

These lines name the default data source liferayDataSource, the counter service data source counterDataSource and similarly analyticsDataSource. These names are all arbitrary, so you can chose other desired values.

The second line gives the counter service data source a new property prefix "jdbc.counter." Use this prefix to set counterDataSource properties you wish to be different from the liferayDataSource. Conversely, any properties not set with this prefix will use the value set using the "jdbc.default." prefix.

Now in JMX, c3p0 beans look like this:

  • com.mchange.v2.c3p0:name=analyticsDataSource,type=PooledDataSource
  • com.mchange.v2.c3p0:name=counterDataSource,type=PooledDataSource
  • com.mchange.v2.c3p0:name=liferayDataSource,type=PooledDataSource

Name Other Data Sources

If your Liferay is configured with other data source(s), you must also give each of them a unique name. Otherwise, multiple MBeans will have the same name as liferayDataSource, and only one of them will be detected by JMX tools.

For example, if you have a third data source defined with prefix "jdbc.sap.", add this line to LIFERAY_HOME/portal-ext.properties:

jdbc.sap.dataSourceName=sapDataSource

Then you should see these data sources:

  • com.mchange.v2.c3p0:name=analyticsDataSource,type=PooledDataSource

  • com.mchange.v2.c3p0:name=counterDataSource,type=PooledDataSource

  • com.mchange.v2.c3p0:name=liferayDataSource,type=PooledDataSource

  • com.mchange.v2.c3p0:name=sapDataSource,type=PooledDataSource

What to Watch

In a JMX monitoring tool, for each data source, monitor these 3 properties of its MBean:

  • numConnectionsAllUsers

  • numBusyConnectionsAllUsers

  • numIdleConnectionsAllUsers

An alert should be configured when numBusyConnectionsAllUsers exceeds a certain percentage of maxPoolSize, which forecasts a possible exhaustion of database connections with that data source.

.

Blogs

Thank you - just one minor nitpicking: Please use CATALINA_OPTS instead of JAVA_OPTS. It doesn't make a big difference in this case, but getting used to prefer CATALINA_OPTS is always good. These values are only required during startup of Tomcat, not during shutdown. JAVA_OPTS will be utilized for every JVM that is started with those settings - and shutdown starts a JVM. (As I said: Minor nitpicking in this case, but just the proper use. If you also add your JMX port settings to JAVA_OPTS, you won't be able to shutdown properly, because the shutdown-JVM would compete for the already allocated port)