/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Middleware LLC. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA * */ package org.hibernate.stat; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.hibernate.cache.Region; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.util.ArrayHelper; /** * @see org.hibernate.stat.Statistics * * @author Gavin King * * @deprecated Use {@link org.hibernate.stat.ConcurrentStatisticsImpl} instead */ @Deprecated public class StatisticsImpl implements Statistics, StatisticsImplementor { //TODO: we should provide some way to get keys of collection of statistics to make it easier to retrieve from a GUI perspective private static final Logger log = LoggerFactory.getLogger(StatisticsImpl.class); private SessionFactoryImplementor sessionFactory; private boolean isStatisticsEnabled; private long startTime; private long sessionOpenCount; private long sessionCloseCount; private long flushCount; private long connectCount; private long prepareStatementCount; private long closeStatementCount; private long entityLoadCount; private long entityUpdateCount; private long entityInsertCount; private long entityDeleteCount; private long entityFetchCount; private long collectionLoadCount; private long collectionUpdateCount; private long collectionRemoveCount; private long collectionRecreateCount; private long collectionFetchCount; private long secondLevelCacheHitCount; private long secondLevelCacheMissCount; private long secondLevelCachePutCount; private long queryExecutionCount; private long queryExecutionMaxTime; private String queryExecutionMaxTimeQueryString; private long queryCacheHitCount; private long queryCacheMissCount; private long queryCachePutCount; private long commitedTransactionCount; private long transactionCount; private long optimisticFailureCount; /** second level cache statistics per region */ private final Map secondLevelCacheStatistics = new HashMap(); /** entity statistics per name */ private final Map entityStatistics = new HashMap(); /** collection statistics per name */ private final Map collectionStatistics = new HashMap(); /** entity statistics per query string (HQL or SQL) */ private final Map queryStatistics = new HashMap(); public StatisticsImpl() { clear(); } public StatisticsImpl(SessionFactoryImplementor sessionFactory) { clear(); this.sessionFactory = sessionFactory; } /** * reset all statistics */ public synchronized void clear() { secondLevelCacheHitCount = 0; secondLevelCacheMissCount = 0; secondLevelCachePutCount = 0; sessionCloseCount = 0; sessionOpenCount = 0; flushCount = 0; connectCount = 0; prepareStatementCount = 0; closeStatementCount = 0; entityDeleteCount = 0; entityInsertCount = 0; entityUpdateCount = 0; entityLoadCount = 0; entityFetchCount = 0; collectionRemoveCount = 0; collectionUpdateCount = 0; collectionRecreateCount = 0; collectionLoadCount = 0; collectionFetchCount = 0; queryExecutionCount = 0; queryCacheHitCount = 0; queryExecutionMaxTime = 0; queryExecutionMaxTimeQueryString = null; queryCacheMissCount = 0; queryCachePutCount = 0; transactionCount = 0; commitedTransactionCount = 0; optimisticFailureCount = 0; secondLevelCacheStatistics.clear(); entityStatistics.clear(); collectionStatistics.clear(); queryStatistics.clear(); startTime = System.currentTimeMillis(); } public synchronized void openSession() { sessionOpenCount++; } public synchronized void closeSession() { sessionCloseCount++; } public synchronized void flush() { flushCount++; } public synchronized void connect() { connectCount++; } public synchronized void loadEntity(String entityName) { entityLoadCount++; ((EntityStatisticsImpl) getEntityStatistics(entityName)).loadCount++; } public synchronized void fetchEntity(String entityName) { entityFetchCount++; ((EntityStatisticsImpl) getEntityStatistics(entityName)).fetchCount++; } /** * find entity statistics per name * * @param entityName entity name * @return EntityStatistics object */ public synchronized EntityStatistics getEntityStatistics(String entityName) { EntityStatisticsImpl es = (EntityStatisticsImpl) entityStatistics.get(entityName); if (es == null) { es = new EntityStatisticsImpl(entityName); entityStatistics.put(entityName, es); } return es; } public synchronized void updateEntity(String entityName) { entityUpdateCount++; EntityStatisticsImpl es = (EntityStatisticsImpl) getEntityStatistics(entityName); es.updateCount++; } public synchronized void insertEntity(String entityName) { entityInsertCount++; EntityStatisticsImpl es = (EntityStatisticsImpl) getEntityStatistics(entityName); es.insertCount++; } public synchronized void deleteEntity(String entityName) { entityDeleteCount++; EntityStatisticsImpl es = (EntityStatisticsImpl) getEntityStatistics(entityName); es.deleteCount++; } /** * Get collection statistics per role * * @param role collection role * @return CollectionStatistics */ public synchronized CollectionStatistics getCollectionStatistics(String role) { CollectionStatisticsImpl cs = (CollectionStatisticsImpl) collectionStatistics.get(role); if (cs==null) { cs = new CollectionStatisticsImpl(role); collectionStatistics.put(role, cs); } return cs; } public synchronized void loadCollection(String role) { collectionLoadCount++; ((CollectionStatisticsImpl) getCollectionStatistics(role)).loadCount++; } public synchronized void fetchCollection(String role) { collectionFetchCount++; ((CollectionStatisticsImpl) getCollectionStatistics(role)).fetchCount++; } public synchronized void updateCollection(String role) { collectionUpdateCount++; ((CollectionStatisticsImpl) getCollectionStatistics(role)).updateCount++; } public synchronized void recreateCollection(String role) { collectionRecreateCount++; ((CollectionStatisticsImpl) getCollectionStatistics(role)).recreateCount++; } public synchronized void removeCollection(String role) { collectionRemoveCount++; ((CollectionStatisticsImpl) getCollectionStatistics(role)).removeCount++; } /** * Second level cache statistics per region * * @param regionName region name * @return SecondLevelCacheStatistics */ public synchronized SecondLevelCacheStatistics getSecondLevelCacheStatistics(String regionName) { SecondLevelCacheStatisticsImpl slcs = (SecondLevelCacheStatisticsImpl) secondLevelCacheStatistics.get(regionName); if ( slcs == null ) { if ( sessionFactory == null ) { return null; } Region region = sessionFactory.getSecondLevelCacheRegion( regionName ); if ( region == null ) { return null; } slcs = new SecondLevelCacheStatisticsImpl(region); secondLevelCacheStatistics.put( regionName, slcs ); } return slcs; } public synchronized void secondLevelCachePut(String regionName) { secondLevelCachePutCount++; ((SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName)).putCount++; } public synchronized void secondLevelCacheHit(String regionName) { secondLevelCacheHitCount++; ((SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName)).hitCount++; } public synchronized void secondLevelCacheMiss(String regionName) { secondLevelCacheMissCount++; ((SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName)).missCount++; } public synchronized void queryExecuted(String hql, int rows, long time) { queryExecutionCount++; if (queryExecutionMaxTime<time) { queryExecutionMaxTime=time; queryExecutionMaxTimeQueryString = hql; } if (hql!=null) { QueryStatisticsImpl qs = (QueryStatisticsImpl) getQueryStatistics(hql); qs.executed(rows, time); log.info( "HQL: {}, time: {}ms, rows: {}", new Object[]{hql, new Long( time ), new Long( rows )} ); } } public synchronized void queryCacheHit(String hql, String regionName) { queryCacheHitCount++; if (hql!=null) { QueryStatisticsImpl qs = (QueryStatisticsImpl) getQueryStatistics(hql); qs.cacheHitCount++; } SecondLevelCacheStatisticsImpl slcs = (SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName); slcs.hitCount++; } public synchronized void queryCacheMiss(String hql, String regionName) { queryCacheMissCount++; if (hql!=null) { QueryStatisticsImpl qs = (QueryStatisticsImpl) getQueryStatistics(hql); qs.cacheMissCount++; } SecondLevelCacheStatisticsImpl slcs = (SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName); slcs.missCount++; } public synchronized void queryCachePut(String hql, String regionName) { queryCachePutCount++; if (hql!=null) { QueryStatisticsImpl qs = (QueryStatisticsImpl) getQueryStatistics(hql); qs.cachePutCount++; } SecondLevelCacheStatisticsImpl slcs = (SecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics(regionName); slcs.putCount++; } /** * Query statistics from query string (HQL or SQL) * * @param queryString query string * @return QueryStatistics */ public synchronized QueryStatistics getQueryStatistics(String queryString) { QueryStatisticsImpl qs = (QueryStatisticsImpl) queryStatistics.get(queryString); if (qs==null) { qs = new QueryStatisticsImpl(queryString); queryStatistics.put(queryString, qs); } return qs; } /** * @return entity deletion count */ public long getEntityDeleteCount() { return entityDeleteCount; } /** * @return entity insertion count */ public long getEntityInsertCount() { return entityInsertCount; } /** * @return entity load (from DB) */ public long getEntityLoadCount() { return entityLoadCount; } /** * @return entity fetch (from DB) */ public long getEntityFetchCount() { return entityFetchCount; } /** * @return entity update */ public long getEntityUpdateCount() { return entityUpdateCount; } public long getQueryExecutionCount() { return queryExecutionCount; } public long getQueryCacheHitCount() { return queryCacheHitCount; } public long getQueryCacheMissCount() { return queryCacheMissCount; } public long getQueryCachePutCount() { return queryCachePutCount; } /** * @return flush */ public long getFlushCount() { return flushCount; } /** * @return session connect */ public long getConnectCount() { return connectCount; } /** * @return second level cache hit */ public long getSecondLevelCacheHitCount() { return secondLevelCacheHitCount; } /** * @return second level cache miss */ public long getSecondLevelCacheMissCount() { return secondLevelCacheMissCount; } /** * @return second level cache put */ public long getSecondLevelCachePutCount() { return secondLevelCachePutCount; } /** * @return session closing */ public long getSessionCloseCount() { return sessionCloseCount; } /** * @return session opening */ public long getSessionOpenCount() { return sessionOpenCount; } /** * @return collection loading (from DB) */ public long getCollectionLoadCount() { return collectionLoadCount; } /** * @return collection fetching (from DB) */ public long getCollectionFetchCount() { return collectionFetchCount; } /** * @return collection update */ public long getCollectionUpdateCount() { return collectionUpdateCount; } /** * @return collection removal * FIXME: even if isInverse="true"? */ public long getCollectionRemoveCount() { return collectionRemoveCount; } /** * @return collection recreation */ public long getCollectionRecreateCount() { return collectionRecreateCount; } /** * @return start time in ms (JVM standards {@link System#currentTimeMillis()}) */ public long getStartTime() { return startTime; } /** * log in info level the main statistics */ public void logSummary() { log.info("Logging statistics...."); log.info("start time: " + startTime); log.info("sessions opened: " + sessionOpenCount); log.info("sessions closed: " + sessionCloseCount); log.info("transactions: " + transactionCount); log.info("successful transactions: " + commitedTransactionCount); log.info("optimistic lock failures: " + optimisticFailureCount); log.info("flushes: " + flushCount); log.info("connections obtained: " + connectCount); log.info("statements prepared: " + prepareStatementCount); log.info("statements closed: " + closeStatementCount); log.info("second level cache puts: " + secondLevelCachePutCount); log.info("second level cache hits: " + secondLevelCacheHitCount); log.info("second level cache misses: " + secondLevelCacheMissCount); log.info("entities loaded: " + entityLoadCount); log.info("entities updated: " + entityUpdateCount); log.info("entities inserted: " + entityInsertCount); log.info("entities deleted: " + entityDeleteCount); log.info("entities fetched (minimize this): " + entityFetchCount); log.info("collections loaded: " + collectionLoadCount); log.info("collections updated: " + collectionUpdateCount); log.info("collections removed: " + collectionRemoveCount); log.info("collections recreated: " + collectionRecreateCount); log.info("collections fetched (minimize this): " + collectionFetchCount); log.info("queries executed to database: " + queryExecutionCount); log.info("query cache puts: " + queryCachePutCount); log.info("query cache hits: " + queryCacheHitCount); log.info("query cache misses: " + queryCacheMissCount); log.info("max query time: " + queryExecutionMaxTime + "ms"); } /** * Are statistics logged */ public boolean isStatisticsEnabled() { return isStatisticsEnabled; } /** * Enable statistics logs (this is a dynamic parameter) */ public void setStatisticsEnabled(boolean b) { isStatisticsEnabled = b; } /** * @return Returns the max query execution time, * for all queries */ public long getQueryExecutionMaxTime() { return queryExecutionMaxTime; } /** * Get all executed query strings */ public String[] getQueries() { return ArrayHelper.toStringArray( queryStatistics.keySet() ); } /** * Get the names of all entities */ public String[] getEntityNames() { if (sessionFactory==null) { return ArrayHelper.toStringArray( entityStatistics.keySet() ); } else { return ArrayHelper.toStringArray( sessionFactory.getAllClassMetadata().keySet() ); } } /** * Get the names of all collection roles */ public String[] getCollectionRoleNames() { if (sessionFactory==null) { return ArrayHelper.toStringArray( collectionStatistics.keySet() ); } else { return ArrayHelper.toStringArray( sessionFactory.getAllCollectionMetadata().keySet() ); } } /** * Get all second-level cache region names */ public String[] getSecondLevelCacheRegionNames() { if (sessionFactory==null) { return ArrayHelper.toStringArray( secondLevelCacheStatistics.keySet() ); } else { return ArrayHelper.toStringArray( sessionFactory.getAllSecondLevelCacheRegions().keySet() ); } } public void endTransaction(boolean success) { transactionCount++; if (success) commitedTransactionCount++; } public long getSuccessfulTransactionCount() { return commitedTransactionCount; } public long getTransactionCount() { return transactionCount; } public void closeStatement() { closeStatementCount++; } public void prepareStatement() { prepareStatementCount++; } public long getCloseStatementCount() { return closeStatementCount; } public long getPrepareStatementCount() { return prepareStatementCount; } public void optimisticFailure(String entityName) { optimisticFailureCount++; ((EntityStatisticsImpl) getEntityStatistics(entityName)).optimisticFailureCount++; } public long getOptimisticFailureCount() { return optimisticFailureCount; } public String toString() { return new StringBuffer() .append("Statistics[") .append("start time=").append(startTime) .append(",sessions opened=").append(sessionOpenCount) .append(",sessions closed=").append(sessionCloseCount) .append(",transactions=").append(transactionCount) .append(",successful transactions=").append(commitedTransactionCount) .append(",optimistic lock failures=").append(optimisticFailureCount) .append(",flushes=").append(flushCount) .append(",connections obtained=").append(connectCount) .append(",statements prepared=").append(prepareStatementCount) .append(",statements closed=").append(closeStatementCount) .append(",second level cache puts=").append(secondLevelCachePutCount) .append(",second level cache hits=").append(secondLevelCacheHitCount) .append(",second level cache misses=").append(secondLevelCacheMissCount) .append(",entities loaded=").append(entityLoadCount) .append(",entities updated=").append(entityUpdateCount) .append(",entities inserted=").append(entityInsertCount) .append(",entities deleted=").append(entityDeleteCount) .append(",entities fetched=").append(entityFetchCount) .append(",collections loaded=").append(collectionLoadCount) .append(",collections updated=").append(collectionUpdateCount) .append(",collections removed=").append(collectionRemoveCount) .append(",collections recreated=").append(collectionRecreateCount) .append(",collections fetched=").append(collectionFetchCount) .append(",queries executed to database=").append(queryExecutionCount) .append(",query cache puts=").append(queryCachePutCount) .append(",query cache hits=").append(queryCacheHitCount) .append(",query cache misses=").append(queryCacheMissCount) .append(",max query time=").append(queryExecutionMaxTime) .append(']') .toString(); } public String getQueryExecutionMaxTimeQueryString() { return queryExecutionMaxTimeQueryString; } }