CORDA-822 - JMX Jolokia instrumentation (#2197)

* JMX Jolokia instrumentation WIP (driverDSL, webserver, cordformation, hibernate statistics, access policy config file hardening)

* Cordformation changes to support jolokia agent instrumentation at JVM startup.

* Minor updates to reflect usage of Jolokia 1.3.7 (which uses slightly different .war naming)

* Use relative path reference in -javaagent to prevent problem with long path names with spaces.

* Fixed incorrect regex pattern and added assertion to test.

* Enable JMX monitoring.

* Reporting of Hibernate JMX statistics is configurable (by default, only switched on in devMode)

* Make Artemis JMX enablement configurable.

* Re-instate banning of java serialization.

* Improve JUnit.

* Fixes following rebase from master.

* Re-instated correct regex for picking up Jolokia agent jar.

* Fixed broken integration test.

* Updated documentation

* Updated following PR review feedback.

* Fixed compilation error caused by change in DriverDSL argument type.

* Fixed compilation error caused by change in DriverDSL argument type.

* Fail fast if jolokia-agent-jvm.jar is not located.

* Applied changes in cordformation following review feedback from CA.
This commit is contained in:
josecoll
2017-12-08 16:27:12 +00:00
committed by GitHub
parent 75ea23d193
commit 4762569200
29 changed files with 489 additions and 71 deletions

View File

@ -20,7 +20,8 @@ const val NODE_DATABASE_PREFIX = "node_"
data class DatabaseConfig(
val initialiseSchema: Boolean = true,
val serverNameTablePrefix: String = "",
val transactionIsolationLevel: TransactionIsolationLevel = TransactionIsolationLevel.REPEATABLE_READ
val transactionIsolationLevel: TransactionIsolationLevel = TransactionIsolationLevel.REPEATABLE_READ,
val exportHibernateJMXStatistics: Boolean = false
)
// This class forms part of the node config and so any changes to it must be handled with care

View File

@ -17,8 +17,10 @@ import org.hibernate.type.AbstractSingleColumnStandardBasicType
import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor
import org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor
import java.lang.management.ManagementFactory
import java.sql.Connection
import java.util.concurrent.ConcurrentHashMap
import javax.management.ObjectName
import javax.persistence.AttributeConverter
class HibernateConfiguration(
@ -60,9 +62,31 @@ class HibernateConfiguration(
val sessionFactory = buildSessionFactory(config, metadataSources, databaseConfig.serverNameTablePrefix)
logger.info("Created session factory for schemas: $schemas")
// export Hibernate JMX statistics
if (databaseConfig.exportHibernateJMXStatistics)
initStatistics(sessionFactory)
return sessionFactory
}
// NOTE: workaround suggested to overcome deprecation of StatisticsService (since Hibernate v4.0)
// https://stackoverflow.com/questions/23606092/hibernate-upgrade-statisticsservice
fun initStatistics(sessionFactory: SessionFactory) {
val statsName = ObjectName("org.hibernate:type=statistics")
val mbeanServer = ManagementFactory.getPlatformMBeanServer()
val statisticsMBean = DelegatingStatisticsService(sessionFactory.statistics)
statisticsMBean.isStatisticsEnabled = true
try {
mbeanServer.registerMBean(statisticsMBean, statsName)
}
catch (e: Exception) {
logger.warn(e.message)
}
}
private fun buildSessionFactory(config: Configuration, metadataSources: MetadataSources, tablePrefix: String): SessionFactory {
config.standardServiceRegistryBuilder.applySettings(config.properties)
val metadata = metadataSources.getMetadataBuilder(config.standardServiceRegistryBuilder.build()).run {

View File

@ -0,0 +1,227 @@
package net.corda.nodeapi.internal.persistence
import javax.management.MXBean
import org.hibernate.stat.Statistics
import org.hibernate.stat.SecondLevelCacheStatistics
import org.hibernate.stat.QueryStatistics
import org.hibernate.stat.NaturalIdCacheStatistics
import org.hibernate.stat.EntityStatistics
import org.hibernate.stat.CollectionStatistics
/**
* Exposes Hibernate [Statistics] contract as JMX resource.
*/
@MXBean
interface StatisticsService : Statistics
/**
* Implements the MXBean interface by delegating through the actual [Statistics] implementation retrieved from the
* session factory.
*/
class DelegatingStatisticsService(private val delegate: Statistics) : StatisticsService {
override fun clear() {
delegate.clear()
}
override fun getCloseStatementCount(): Long {
return delegate.closeStatementCount
}
override fun getCollectionFetchCount(): Long {
return delegate.collectionFetchCount
}
override fun getCollectionLoadCount(): Long {
return delegate.collectionLoadCount
}
override fun getCollectionRecreateCount(): Long {
return delegate.collectionRecreateCount
}
override fun getCollectionRemoveCount(): Long {
return delegate.collectionRemoveCount
}
override fun getCollectionRoleNames(): Array<String> {
return delegate.collectionRoleNames
}
override fun getCollectionStatistics(arg0: String): CollectionStatistics {
return delegate.getCollectionStatistics(arg0)
}
override fun getCollectionUpdateCount(): Long {
return delegate.collectionUpdateCount
}
override fun getConnectCount(): Long {
return delegate.connectCount
}
override fun getEntityDeleteCount(): Long {
return delegate.entityDeleteCount
}
override fun getEntityFetchCount(): Long {
return delegate.entityFetchCount
}
override fun getEntityInsertCount(): Long {
return delegate.entityInsertCount
}
override fun getEntityLoadCount(): Long {
return delegate.entityLoadCount
}
override fun getEntityNames(): Array<String> {
return delegate.entityNames
}
override fun getEntityStatistics(arg0: String): EntityStatistics {
return delegate.getEntityStatistics(arg0)
}
override fun getEntityUpdateCount(): Long {
return delegate.entityUpdateCount
}
override fun getFlushCount(): Long {
return delegate.flushCount
}
override fun getNaturalIdCacheHitCount(): Long {
return delegate.naturalIdCacheHitCount
}
override fun getNaturalIdCacheMissCount(): Long {
return delegate.naturalIdCacheMissCount
}
override fun getNaturalIdCachePutCount(): Long {
return delegate.naturalIdCachePutCount
}
override fun getNaturalIdCacheStatistics(arg0: String): NaturalIdCacheStatistics {
return delegate.getNaturalIdCacheStatistics(arg0)
}
override fun getNaturalIdQueryExecutionCount(): Long {
return delegate.naturalIdQueryExecutionCount
}
override fun getNaturalIdQueryExecutionMaxTime(): Long {
return delegate.naturalIdQueryExecutionMaxTime
}
override fun getNaturalIdQueryExecutionMaxTimeRegion(): String {
return delegate.naturalIdQueryExecutionMaxTimeRegion
}
override fun getOptimisticFailureCount(): Long {
return delegate.optimisticFailureCount
}
override fun getPrepareStatementCount(): Long {
return delegate.prepareStatementCount
}
override fun getQueries(): Array<String> {
return delegate.queries
}
override fun getQueryCacheHitCount(): Long {
return delegate.queryCacheHitCount
}
override fun getQueryCacheMissCount(): Long {
return delegate.queryCacheMissCount
}
override fun getQueryCachePutCount(): Long {
return delegate.queryCachePutCount
}
override fun getQueryExecutionCount(): Long {
return delegate.queryExecutionCount
}
override fun getQueryExecutionMaxTime(): Long {
return delegate.queryExecutionMaxTime
}
override fun getQueryExecutionMaxTimeQueryString(): String {
return delegate.queryExecutionMaxTimeQueryString
}
override fun getQueryStatistics(arg0: String): QueryStatistics {
return delegate.getQueryStatistics(arg0)
}
override fun getSecondLevelCacheHitCount(): Long {
return delegate.secondLevelCacheHitCount
}
override fun getSecondLevelCacheMissCount(): Long {
return delegate.secondLevelCacheMissCount
}
override fun getSecondLevelCachePutCount(): Long {
return delegate.secondLevelCachePutCount
}
override fun getSecondLevelCacheRegionNames(): Array<String> {
return delegate.secondLevelCacheRegionNames
}
override fun getSecondLevelCacheStatistics(arg0: String): SecondLevelCacheStatistics {
return delegate.getSecondLevelCacheStatistics(arg0)
}
override fun getSessionCloseCount(): Long {
return delegate.sessionCloseCount
}
override fun getSessionOpenCount(): Long {
return delegate.sessionOpenCount
}
override fun getStartTime(): Long {
return delegate.startTime
}
override fun getSuccessfulTransactionCount(): Long {
return delegate.successfulTransactionCount
}
override fun getTransactionCount(): Long {
return delegate.transactionCount
}
override fun getUpdateTimestampsCacheHitCount(): Long {
return delegate.updateTimestampsCacheHitCount
}
override fun getUpdateTimestampsCacheMissCount(): Long {
return delegate.updateTimestampsCacheMissCount
}
override fun getUpdateTimestampsCachePutCount(): Long {
return delegate.updateTimestampsCachePutCount
}
override fun isStatisticsEnabled(): Boolean {
return delegate.isStatisticsEnabled
}
override fun logSummary() {
delegate.logSummary()
}
override fun setStatisticsEnabled(arg0: Boolean) {
delegate.isStatisticsEnabled = arg0
}
}