mirror of
https://github.com/corda/corda.git
synced 2025-06-14 05:08:18 +00:00
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:
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user