#

Hibernate Statistics JSP

Neulich zusammen gefummelt und als sinnvoll empfunden: Eine JSP die alle Hibernate-Statistiken aktivieren/deaktivieren und anzeigen kann. Dieser Artikel wurde durch den neueren Artikel Hibernate Statistics JSP Reloaded abgelöst

Die JSP benutzt lediglich zwei Methoden, die hier nicht mitgeliefert werden, aber trivial sind:
StringUtils.format(Date date, String format) zum formatierten Darstellen eines Datums und meine in einem anderen Eintrag bereits vorgestellten HTMLEscapeWriter.
Außerdem muss die JSP Seite irgenwie Zugriff auf die SessionFactory für Hibernate zugriff haben.

<jsp:directive.page import="narcanti.service.Services"/>
<jsp:directive.page import="java.util.*"/>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<jsp:directive.page import="narcanti.util.HTMLEscapeWriter"/>
<jsp:directive.page import="org.hibernate.SessionFactory"/>
<jsp:directive.page import="org.hibernate.stat.Statistics"/>
<jsp:directive.page import="narcanti.util.StringUtils"/>
<jsp:directive.page import="org.hibernate.stat.QueryStatistics"/>
<jsp:directive.page import="java.text.Collator"/>
<jsp:directive.page import="org.hibernate.stat.EntityStatistics"/>
<jsp:directive.page import="org.hibernate.stat.CollectionStatistics"/>
<jsp:directive.page import="org.hibernate.stat.SecondLevelCacheStatistics"/>
<%!
	static Map<String, QueryStatistics> queryStatistics = 
		Collections.synchronizedMap(
		new TreeMap<String, QueryStatistics>(Collator.getInstance()));
	static Map<String, EntityStatistics> entityStatistics = 
		Collections.synchronizedMap(
		new TreeMap<String, EntityStatistics>(Collator.getInstance()));
	static Map<String, CollectionStatistics> collectionStatistics = 
		Collections.synchronizedMap(
		new TreeMap<String, CollectionStatistics>(Collator.getInstance()));
	static Map<String, SecondLevelCacheStatistics> secondLevelCacheStatistics = 
		Collections.synchronizedMap(
		new TreeMap<String, SecondLevelCacheStatistics>(Collator.getInstance()));
	static List<Long> generalStatistics = 
		Collections.synchronizedList(new ArrayList<Long>(18));
	static{
		for (int i=0; i<9; i++){
			generalStatistics.add(new Long(-1));
		}
	}
	static Date lastUpdate;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Hibernate statistics</title>
	<link href="../default.css" rel="stylesheet" type="text/css"></link>
</head>
<body>
<p/>
<%
	String action = request.getParameter("do");
	StringBuilder errors = new StringBuilder(512);
	StringBuilder warnings = new StringBuilder(512);
	StringBuilder info = new StringBuilder(512);
 
	// hier die Session Factory von Hibernate holen
	SessionFactory sessionFactory = Services.getInstance().getSessionFactory();
	Statistics statistics = sessionFactory.getStatistics();
 
	if ("activate".equals(action) && !statistics.isStatisticsEnabled()){
		statistics.setStatisticsEnabled(true);
		info.append("Statistics enabled\n");
	}
	else if ("deactivate".equals(action) && statistics.isStatisticsEnabled()){
		statistics.setStatisticsEnabled(false);
		info.append("Statistics disabled\n");
	}
 
	boolean active = statistics.isStatisticsEnabled();
 
	if (errors.length()>0){
		%>
		<p/>
		<div class="error"><%=HTMLEscapeWriter.escape(errors.toString())%></div>
		<%
	}
	if (warnings.length()>0){
		%>
		<p/>
		<div class="warn"><%=HTMLEscapeWriter.escape(warnings.toString())%></div>
		<%
	}
	if (info.length()>0){
		%>
		<p/>
		<div class="success"><%=HTMLEscapeWriter.escape(info.toString())%></div>
		<%
	}
	%>
<p/>
<a href="hibernate.jsp">Reload</a>
<p/>
<a href="hibernate.jsp?do=<%=(active?"deactivate":"activate")%>">
<%=(active?"DEACTIVATE":"ACTIVATE")%></a>
<%
	if (active){
		lastUpdate = new Date();
		String [] names;
 
		generalStatistics.set(0, statistics.getConnectCount());
		generalStatistics.set(1, statistics.getFlushCount());
 
		generalStatistics.set(2, statistics.getPrepareStatementCount());
		generalStatistics.set(3, statistics.getCloseStatementCount());
 
		generalStatistics.set(4, statistics.getSessionCloseCount());
		generalStatistics.set(5, statistics.getSessionOpenCount());
 
		generalStatistics.set(6, statistics.getTransactionCount());
		generalStatistics.set(7, statistics.getSuccessfulTransactionCount());
		generalStatistics.set(8, statistics.getOptimisticFailureCount());
 
		queryStatistics.clear();
		names = statistics.getQueries();
		if (names!=null && names.length>0){
			for (int i=0; i<names.length; i++){
				queryStatistics.put(names[i], 
					statistics.getQueryStatistics(names[i]));
			}
		}
 
		entityStatistics.clear();
		names = statistics.getEntityNames();
		if (names!=null && names.length>0){
			for (int i=0; i<names.length; i++){
				entityStatistics.put(names[i], 
					statistics.getEntityStatistics(names[i]));
			}
		}
 
		collectionStatistics.clear();
		names = statistics.getCollectionRoleNames();
		if (names!=null && names.length>0){
			for (int i=0; i<names.length; i++){
				collectionStatistics.put(names[i], 
					statistics.getCollectionStatistics(names[i]));
			}
		}
 
		secondLevelCacheStatistics.clear();
		names = statistics.getSecondLevelCacheRegionNames();
		if (names!=null && names.length>0){
			for (int i=0; i<names.length; i++){
				secondLevelCacheStatistics.put(names[i], 
					statistics.getSecondLevelCacheStatistics(names[i]));
			}
		}
	}
 
	%>
	<p/>
	Last update: <%=(lastUpdate!=null?StringUtils.format(lastUpdate, 
		"dd.MM.yy HH:mm:ss"):"none")%>
	<p/>
	<%
	boolean hasGeneral = false;
	for (int i=0; i<9; i++){
		if (generalStatistics.get(i).longValue()>-1){
			hasGeneral = true;
			break;
		}
	}
	if (hasGeneral){
		%>
		<table>
			<tr>
				<th class="c bd1 bg1">Connects</th>
				<td><%=generalStatistics.get(0)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Flushes</th>
				<td><%=generalStatistics.get(1)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Prepare statements</th>
				<td><%=generalStatistics.get(2)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Close statements</th>
				<td><%=generalStatistics.get(3)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Session opens</th>
				<td><%=generalStatistics.get(5)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Session closes</th>
				<td><%=generalStatistics.get(4)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Total Transactions</th>
				<td><%=generalStatistics.get(6)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Successfull Transactions</th>
				<td><%=generalStatistics.get(7)%></td>
			</tr>
			<tr>
				<th class="c bd1 bg1">Optimistic failures</th>
				<td><%=generalStatistics.get(8)%></td>
			</tr>
		</table>
		<p/>
		<%
	}
	%>
 
	<%
	if (queryStatistics.size()>0){
		%>
		<table width="100%">
			<tr><th colspan="10" class="c bd1 bg2">Query statistics</th></tr>
			<tr>
				<th class="c bd1 bg1">Query</th>
				<th class="c bd1 bg1">Calls</th>
				<th class="c bd1 bg1">Total rowcount</th>
				<th class="c bd1 bg1">Max dur.</th>
				<th class="c bd1 bg1">Min dur.</th>
				<th class="c bd1 bg1">Avg dur.</th>
				<th class="c bd1 bg1">Total dur.</th>
				<th class="c bd1 bg1">Cache hits</th>
				<th class="c bd1 bg1">Cache miss</th>
				<th class="c bd1 bg1">Cache put</th>
			</tr>
		<%
		Iterator<String> queryIter = queryStatistics.keySet().iterator();
		String query;
		QueryStatistics queryStats;
		boolean odd = true;
		while (queryIter.hasNext()){
			query = queryIter.next();
			queryStats = queryStatistics.get(query);
			%>
			<tr class="<%=(odd?"odd":"even")%>">
				<td><%=query%></td>
				<td><%=queryStats.getExecutionCount()%></td>
				<td><%=queryStats.getExecutionRowCount()%></td>
				<td><%=queryStats.getExecutionMaxTime()%></td>
				<td><%=queryStats.getExecutionMinTime()%></td>
				<td><%=queryStats.getExecutionAvgTime()%></td>
				<td><%=queryStats.getExecutionAvgTime()*queryStats.getExecutionCount()%></td>
				<td><%=queryStats.getCacheHitCount()%></td>
				<td><%=queryStats.getCacheMissCount()%></td>
				<td><%=queryStats.getCachePutCount()%></td>
			</tr>
			<%
			odd = !odd;
		}
		%>
		</table>
		<p/>
	<%
	}
 
	if (entityStatistics.size()>0){
	%>
		<table width="100%">
			<tr><th colspan="7" class="c bd1 bg2">Entity statistics</th></tr>
			<tr>
				<th class="c bd1 bg1">Entity</th>
				<th class="c bd1 bg1">Loads</th>
				<th class="c bd1 bg1">Fetches</th>
				<th class="c bd1 bg1">Inserts</th>
				<th class="c bd1 bg1">Updates</th>
				<th class="c bd1 bg1">Deletes</th>
				<th class="c bd1 bg1">Optimistic failures</th>
			</tr>
		<%
		Iterator<String> entityIter = entityStatistics.keySet().iterator();
		String entity;
		EntityStatistics entityStats;
		boolean odd = true;
		while (entityIter.hasNext()){
			entity = entityIter.next();
			entityStats = entityStatistics.get(entity);
			%>
			<tr class="<%=(odd?"odd":"even")%>">
				<td><%=entity%></td>
				<td><%=entityStats.getLoadCount()%></td>
				<td><%=entityStats.getFetchCount()%></td>
				<td><%=entityStats.getInsertCount()%></td>
				<td><%=entityStats.getUpdateCount()%></td>
				<td><%=entityStats.getDeleteCount()%></td>
				<td><%=entityStats.getOptimisticFailureCount()%></td>
			</tr>
			<%
			odd = !odd;
		}
		%>
		</table>
		<p/>
	<%
	}
 
	if (collectionStatistics.size()>0){
	%>
		<table width="100%">
			<tr><th colspan="6" class="c bd1 bg2">Collection statistics</th></tr>
			<tr>
				<th class="c bd1 bg1">Role</th>
				<th class="c bd1 bg1">Loads</th>
				<th class="c bd1 bg1">Fetches</th>
				<th class="c bd1 bg1">Updates</th>
				<th class="c bd1 bg1">Recreate</th>
				<th class="c bd1 bg1">Remove</th>
			</tr>
		<%
		Iterator<String> collectionIter = collectionStatistics.keySet().iterator();
		String collection;
		CollectionStatistics collectionStats;
		boolean odd = true;
		while (collectionIter.hasNext()){
			collection = collectionIter.next();
			collectionStats = collectionStatistics.get(collection);
			%>
			<tr class="<%=(odd?"odd":"even")%>">
				<td><%=collection%></td>
				<td><%=collectionStats.getLoadCount()%></td>
				<td><%=collectionStats.getFetchCount()%></td>
				<td><%=collectionStats.getUpdateCount()%></td>
				<td><%=collectionStats.getRecreateCount()%></td>
				<td><%=collectionStats.getRemoveCount()%></td>
			</tr>
			<%
			odd = !odd;
		}
		%>
		</table>
		<p/>
	<%
	}
 
	if (secondLevelCacheStatistics.size()>0){
	%>
		<table width="100%">
			<tr><th colspan="7" class="c bd1 bg2">2nd level cache statistics</th></tr>
			<tr>
				<th class="c bd1 bg1">Regionname</th>
				<th class="c bd1 bg1">Puts</th>
				<th class="c bd1 bg1">Hits</th>
				<th class="c bd1 bg1">Misses</th>
				<th class="c bd1 bg1">Elements in memory</th>
				<th class="c bd1 bg1">Size in memory</th>
				<th class="c bd1 bg1">Elements on disk</th>
			</tr>
		<%
		Iterator<String> cacheIter = secondLevelCacheStatistics.keySet().iterator();
		String cache;
		SecondLevelCacheStatistics cacheStats;
		boolean odd = true;
		while (cacheIter.hasNext()){
			cache = cacheIter.next();
			cacheStats = secondLevelCacheStatistics.get(cache);
			%>
			<tr class="<%=(odd?"odd":"even")%>">
				<td><%=cache%></td>
				<td><%=cacheStats.getPutCount()%></td>
				<td><%=cacheStats.getHitCount()%></td>
				<td><%=cacheStats.getMissCount()%></td>
				<td><%=cacheStats.getElementCountInMemory()%></td>
				<td><%=cacheStats.getSizeInMemory()%></td>
				<td><%=cacheStats.getElementCountOnDisk()%></td>
			</tr>
			<%
			odd = !odd;
		}
		%>
		</table>
		<p/>
	<%
	}
	%>
</body>
</html>

3 Responses to “Hibernate Statistics JSP” »»

  1. Comment by Toni | 16:23 16.10.07|X

    Wow, coole Idee. Der Java purist in mir rebelliert nur gegen dieses JSP/HTML/Code Mischmasch-Antipattern…naja aber wer unschuldig ist werfe den ersten Stein 😉

  2. Comment by Secco | 10:02 18.10.07|X

    Das Pattern nennt sich „Quick and dirty – but functional“ 😉

  3. Comment by Ralf | 15:26 09.03.09|X

    Wie wäre es mit einem Beispiel Screenshot?

Leave a Reply »»

Note: All comments are manually approved to avoid spam. So if your comment doesn't appear immediately, that's ok. Have patience, it can take some days until I have the time to approve my comments.