exo-jcr SVN: r2277 - in jcr/trunk: exo.jcr.component.statistics/src/main/resources/META-INF and 1 other directories.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 09:10:14 -0400 (Tue, 13 Apr 2010)
New Revision: 2277
Modified:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml
jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml
Log:
EXOJCR-611: The interface org.exoplatform.services.jcr.core.ExtendedProperty has been replaced by javax.jcr.Property since it is never used
Modified: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 09:35:42 UTC (rev 2276)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 13:10:14 UTC (rev 2277)
@@ -214,7 +214,7 @@
<para>In order to know exactly how your application uses eXo JCR, it cans
be interesting to register all the JCR API accesses in order to easily
create real life test scenario based on pure JCR calls and also to tune
- your eXo JCR to better fit your requirements. </para>
+ your eXo JCR to better fit your requirements.</para>
<para>In order to allow you to specify into the configuration which part
of eXo JCR needs to be monitored whitout applying any changes in your code
@@ -250,11 +250,11 @@
<para>By default, the configuration will collect statistcs on all the
methods of the internal interfaces
- <emphasis>org.exoplatform.services.jcr.core.ExtendedSession</emphasis>,
- <emphasis>org.exoplatform.services.jcr.core.ExtendedNode</emphasis> and
- <emphasis>org.exoplatform.services.jcr.core.ExtendedProperty</emphasis>.
- To add and/or remove some interfaces to monitor, you have two
- configuration files to change that are bundled into the jar
+ <emphasis>org.exoplatform.services.jcr.core.ExtendedSession</emphasis> and
+ <emphasis>org.exoplatform.services.jcr.core.ExtendedNode</emphasis>, and
+ the JCR API interface <emphasis>javax.jcr.Property</emphasis>. To add
+ and/or remove some interfaces to monitor, you have two configuration files
+ to change that are bundled into the jar
<emphasis>exo.jcr.component.statistics-X.Y.Z</emphasis>.jar, which are
<emphasis>conf/configuration.xml</emphasis> and
<emphasis>META-INF/aop.xml</emphasis>.</para>
@@ -275,7 +275,7 @@
<name>targetInterfaces</name>
<value>org.exoplatform.services.jcr.core.ExtendedSession</value>
<value>org.exoplatform.services.jcr.core.ExtendedNode</value>
- <value>org.exoplatform.services.jcr.core.ExtendedProperty</value>
+ <value>javax.jcr.Property</value>
</values-param>
</init-params>
</component>
@@ -287,17 +287,16 @@
into the expression filter of the pointcut called
<emphasis>JCRAPIPointcut</emphasis>. As you can see below, by default only
JCR API calls from the exoplatform packages are took into account, don't
- hesistate to modify also this filter to add your own package names.
- </para>
+ hesistate to modify also this filter to add your own package names.</para>
<programlisting><aspectj>
<aspects>
<concrete-aspect name="org.exoplatform.services.jcr.statistics.JCRAPIAspectImpl" extends="org.exoplatform.services.jcr.statistics.JCRAPIAspect">
<pointcut name="JCRAPIPointcut"
- expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(org.exoplatform.services.jcr.core.ExtendedProperty)) &amp;&amp; call(public * *(..))" />
+ expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(javax.jcr.Property)) &amp;&amp; call(public * *(..))" />
</concrete-aspect>
</aspects>
- <weaver>
+ <weaver options="-XnoInline">
<include within="org.exoplatform..*" />
</weaver>
</aspectj> </programlisting>
Modified: jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml 2010-04-13 09:35:42 UTC (rev 2276)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml 2010-04-13 13:10:14 UTC (rev 2277)
@@ -3,10 +3,10 @@
<aspects>
<concrete-aspect name="org.exoplatform.services.jcr.statistics.JCRAPIAspectImpl" extends="org.exoplatform.services.jcr.statistics.JCRAPIAspect">
<pointcut name="JCRAPIPointcut"
- expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(org.exoplatform.services.jcr.core.ExtendedProperty)) && call(public * *(..))" />
+ expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(javax.jcr.Property)) && call(public * *(..))" />
</concrete-aspect>
</aspects>
- <weaver>
+ <weaver options="-XnoInline">
<include within="org.exoplatform..*" />
</weaver>
</aspectj>
\ No newline at end of file
Modified: jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml 2010-04-13 09:35:42 UTC (rev 2276)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml 2010-04-13 13:10:14 UTC (rev 2277)
@@ -17,7 +17,7 @@
<name>targetInterfaces</name>
<value>org.exoplatform.services.jcr.core.ExtendedSession</value>
<value>org.exoplatform.services.jcr.core.ExtendedNode</value>
- <value>org.exoplatform.services.jcr.core.ExtendedProperty</value>
+ <value>javax.jcr.Property</value>
</values-param>
</init-params>
</component>
16 years
exo-jcr SVN: r2276 - core/trunk/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-04-13 05:35:42 -0400 (Tue, 13 Apr 2010)
New Revision: 2276
Modified:
core/trunk/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java
Log:
EXOJCR-662: avoid infinite loop
Modified: core/trunk/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java
===================================================================
--- core/trunk/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java 2010-04-13 09:34:56 UTC (rev 2275)
+++ core/trunk/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java 2010-04-13 09:35:42 UTC (rev 2276)
@@ -142,7 +142,7 @@
while (next != null)
{
errorTrace += next.getMessage() + "; ";
- next = e.getNextException();
+ next = next.getNextException();
}
Throwable cause = e.getCause();
log.error("Could not create db schema of DataSource: '" + dsName + "'. Reason: " + e.getMessage() + "; "
16 years
exo-jcr SVN: r2275 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-04-13 05:34:56 -0400 (Tue, 13 Apr 2010)
New Revision: 2275
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java
Log:
EXOJCR-662: avoid infinite loop
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java 2010-04-13 09:33:55 UTC (rev 2274)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java 2010-04-13 09:34:56 UTC (rev 2275)
@@ -366,7 +366,7 @@
while (next != null)
{
errorTrace += next.getMessage() + "; ";
- next = e.getNextException();
+ next = next.getNextException();
}
Throwable cause = e.getCause();
String msg =
16 years
exo-jcr SVN: r2274 - jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 05:33:55 -0400 (Tue, 13 Apr 2010)
New Revision: 2274
Modified:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
Log:
EXOJCR-611: doc update
Modified: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 09:18:45 UTC (rev 2273)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 09:33:55 UTC (rev 2274)
@@ -261,8 +261,8 @@
<para>The file content below is the content of
<emphasis>conf/configuration.xml</emphasis> that you will need to modify
- to add and/or remove the full qualified name of the interface to monitor,
- into the list of value parameters of the init param called
+ to add and/or remove the full qualified name of the interfaces to monitor,
+ into the list of parameter values of the init param called
<emphasis>targetInterfaces</emphasis>.</para>
<programlisting><configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
@@ -283,7 +283,7 @@
<para>The file content below is the content of
<emphasis>META-INF/aop.xml</emphasis> that you will to need to modify to
- add and/or remove the full qualified name of the interface to monitor,
+ add and/or remove the full qualified name of the interfaces to monitor,
into the expression filter of the pointcut called
<emphasis>JCRAPIPointcut</emphasis>. As you can see below, by default only
JCR API calls from the exoplatform packages are took into account, don't
@@ -336,8 +336,6 @@
figures described below for each method and globaly for all the
methods.</para>
- <para>See below the description of each metric type:</para>
-
<para><table>
<title>Metric Alias</title>
16 years
exo-jcr SVN: r2273 - core/branches/2.4.x/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-04-13 05:18:45 -0400 (Tue, 13 Apr 2010)
New Revision: 2273
Modified:
core/branches/2.4.x/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java
Log:
EXOJCR-662: avoid infinite loop
Modified: core/branches/2.4.x/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java
===================================================================
--- core/branches/2.4.x/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java 2010-04-13 09:16:55 UTC (rev 2272)
+++ core/branches/2.4.x/exo.core.component.database/src/main/java/org/exoplatform/services/database/jdbc/DBSchemaCreator.java 2010-04-13 09:18:45 UTC (rev 2273)
@@ -142,7 +142,7 @@
while (next != null)
{
errorTrace += next.getMessage() + "; ";
- next = e.getNextException();
+ next = next.getNextException();
}
Throwable cause = e.getCause();
log.error("Could not create db schema of DataSource: '" + dsName + "'. Reason: " + e.getMessage() + "; "
16 years
exo-jcr SVN: r2272 - jcr/branches/1.14.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-04-13 05:16:55 -0400 (Tue, 13 Apr 2010)
New Revision: 2272
Modified:
jcr/branches/1.14.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java
Log:
EXOJCR-662: avoid infinite loop
Modified: jcr/branches/1.14.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java
===================================================================
--- jcr/branches/1.14.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java 2010-04-13 07:53:42 UTC (rev 2271)
+++ jcr/branches/1.14.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/jdbc/DBInitializer.java 2010-04-13 09:16:55 UTC (rev 2272)
@@ -366,7 +366,7 @@
while (next != null)
{
errorTrace += next.getMessage() + "; ";
- next = e.getNextException();
+ next = next.getNextException();
}
Throwable cause = e.getCause();
String msg =
16 years
exo-jcr SVN: r2271 - in kernel/trunk/exo.kernel.container/src: main/java/org/exoplatform/container/monitor/jvm and 2 other directories.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 03:53:42 -0400 (Tue, 13 Apr 2010)
New Revision: 2271
Modified:
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/management/ManageableContainer.java
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/monitor/jvm/J2EEServerInfo.java
kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/management/jmx/impl/JMXManagementProvider.java
kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/jmx/support/ManagedManagementAware.java
Log:
EXOJCR-661: Now by default we use the MBeanServer from the platform
Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/management/ManageableContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/management/ManageableContainer.java 2010-04-13 07:47:05 UTC (rev 2270)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/management/ManageableContainer.java 2010-04-13 07:53:42 UTC (rev 2271)
@@ -34,7 +34,6 @@
import org.picocontainer.defaults.ComponentAdapterFactory;
import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
-import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -52,12 +51,7 @@
private static MBeanServer findMBeanServer()
{
J2EEServerInfo serverenv_ = new J2EEServerInfo();
- MBeanServer server = serverenv_.getMBeanServer();
- if (server == null)
- {
- server = ManagementFactory.getPlatformMBeanServer();
- }
- return server;
+ return serverenv_.getMBeanServer();
}
/** . */
Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/monitor/jvm/J2EEServerInfo.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/monitor/jvm/J2EEServerInfo.java 2010-04-13 07:47:05 UTC (rev 2270)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/monitor/jvm/J2EEServerInfo.java 2010-04-13 07:53:42 UTC (rev 2271)
@@ -19,11 +19,11 @@
package org.exoplatform.container.monitor.jvm;
import java.io.File;
+import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URL;
import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
/**
* @author Tuan Nguyen (tuan08(a)users.sourceforge.net)
@@ -149,8 +149,11 @@
serverName_ = "standalone";
serverHome_ = System.getProperty("user.dir");
exoConfDir_ = serverHome_ + "/" + confDirName;
- mbeanServer = MBeanServerFactory.createMBeanServer();
}
+ if (mbeanServer == null)
+ {
+ mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ }
String exoConfHome = System.getProperty(EXO_CONF_PARAM);
if (exoConfHome != null && exoConfHome.length() > 0)
Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/management/jmx/impl/JMXManagementProvider.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/management/jmx/impl/JMXManagementProvider.java 2010-04-13 07:47:05 UTC (rev 2270)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/management/jmx/impl/JMXManagementProvider.java 2010-04-13 07:53:42 UTC (rev 2271)
@@ -18,11 +18,16 @@
*/
package org.exoplatform.management.jmx.impl;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
import org.exoplatform.management.spi.ManagedResource;
import org.exoplatform.management.spi.ManagementProvider;
-import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
-import javax.management.InstanceAlreadyExistsException;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
@@ -30,9 +35,6 @@
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBeanInfo;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.List;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
@@ -41,6 +43,11 @@
public class JMXManagementProvider implements ManagementProvider
{
+ /**
+ * The logger
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.kernel.container.JMXManagementProvider");
+
/** . */
private final MBeanServer server;
@@ -136,24 +143,25 @@
{
synchronized (server)
{
- try
+ if (server.isRegistered(name))
{
- server.registerMBean(mbean, name);
- }
- catch (InstanceAlreadyExistsException e)
- {
+ if (LOG.isTraceEnabled())
+ {
+ LOG.trace("The MBean '" + name + " has already been registered, it will be unregistered and then re-registered");
+ }
try
{
-
- server.unregisterMBean(name);
- server.registerMBean(mbean, name);
-
+ server.unregisterMBean(name);
}
- catch (Exception e1)
+ catch (Exception e)
{
- throw new RuntimeException("Failed to register MBean '" + name + " due to " + e.getMessage(), e);
+ throw new RuntimeException("Failed to unregister MBean '" + name + " due to " + e.getMessage(), e);
}
}
+ try
+ {
+ server.registerMBean(mbean, name);
+ }
catch (Exception e)
{
throw new RuntimeException("Failed to register MBean '" + name + " due to " + e.getMessage(), e);
Modified: kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/jmx/support/ManagedManagementAware.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/jmx/support/ManagedManagementAware.java 2010-04-13 07:47:05 UTC (rev 2270)
+++ kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/jmx/support/ManagedManagementAware.java 2010-04-13 07:53:42 UTC (rev 2271)
@@ -43,7 +43,6 @@
public void setContext(ManagementContext context)
{
- this.context = context;
//
if (count == 0)
@@ -52,7 +51,8 @@
{
failure = new AssertionError();
}
- context.register(foo);
+ this.context = context;
+ this.context.register(foo);
count = 1;
}
else if (count == 1)
@@ -61,7 +61,7 @@
{
failure = new AssertionError();
}
- context.unregister(foo);
+ this.context.unregister(foo);
}
else
{
16 years
exo-jcr SVN: r2270 - jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 03:47:05 -0400 (Tue, 13 Apr 2010)
New Revision: 2270
Modified:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
Log:
EXOJCR-611: doc
Modified: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 07:42:49 UTC (rev 2269)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2010-04-13 07:47:05 UTC (rev 2270)
@@ -1,253 +1,468 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="ch_statistics">
- <?dbhtml filename="ch-statistics"?>
-
- <title>eXo JCR statistics</title>
-
- <section>
- <title>Statistics on the Database Access Layer</title>
-
- <para>In order to have a better idea of the time spent into the database
- access layer, it cans be interesting to get some statistics on that part
- of the code, knowing that most of the time spent into eXo JCR is mainly
- the database access. This statistics will then allow you to identify
- without using any profiler what is anormally slow in this layer, which
- could help to fix the problem quickly.</para>
-
- <para>In case you use
- <envar>org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer</envar>
- or
- <envar>org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer</envar>
- as <envar>WorkspaceDataContainer</envar>, you can get statistics on the
- time spent into the database access layer. The database access layer (in
- eXo JCR) is represented by the methods of the interface
- <envar>org.exoplatform.services.jcr.storage.WorkspaceStorageConnection</envar>,
- so for all the methods defined in this interface, we can have the
- following figures: </para>
-
- <itemizedlist>
- <listitem>
- <para>The minimum time spent into the method.</para>
- </listitem>
-
- <listitem>
- <para>The maximum time spent into the method.</para>
- </listitem>
-
- <listitem>
- <para>The average time spent into the method.</para>
- </listitem>
-
- <listitem>
- <para>The total amount of time spent into the method.</para>
- </listitem>
-
- <listitem>
- <para>The total amount of times the method has been called.</para>
- </listitem>
- </itemizedlist>
-
- <para>Those figures are also available globaly for all the methods which
- gives us the global behavior of this layer.</para>
-
- <para>If you want to enable the statistics, you just need to set the JVM
- parameter called
- <emphasis>JDBCWorkspaceDataContainer.statistics.enabled</emphasis> to
- <emphasis>true</emphasis>. This will then create at startup a file called
- <emphasis>StatisticsJDBCStorageConnection-${creation-timestamp}.csv</emphasis>
- into the user directory if it is possible otherwise it will create it into
- the temporary directory. The format of this file is <envar>CSV</envar>
- (i.e. Comma-Seperated Values), one new line will be added every 5 seconds
- and one last line will be added at JVM exit. Each line, will be composed
- of the 5 figures described above for each method and globaly for all the
- methods.</para>
-
- <para>The format of each column header is
- ${method-alias}-${metric-alias}.</para>
-
- <table>
- <title>Method Alias</title>
-
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>global</entry>
-
- <entry>This is the alias for all the methods.</entry>
- </row>
-
- <row>
- <entry>getItemDataById</entry>
-
- <entry>This is the alias for the method
- <emphasis>getItemData(String identifier).</emphasis></entry>
- </row>
-
- <row>
- <entry>getItemDataByNodeDataNQPathEntry</entry>
-
- <entry>This is the alias for the method
- <emphasis>getItemData(NodeData parentData, QPathEntry
- name).</emphasis></entry>
- </row>
-
- <row>
- <entry>getChildNodesData</entry>
-
- <entry>This is the alias for the method
- <emphasis>getChildNodesData(NodeData parent).</emphasis></entry>
- </row>
-
- <row>
- <entry>getChildNodesCount</entry>
-
- <entry>This is the alias for the method
- <emphasis>getChildNodesCount(NodeData parent).</emphasis></entry>
- </row>
-
- <row>
- <entry>getChildPropertiesData</entry>
-
- <entry>This is the alias for the method
- <emphasis>getChildPropertiesData(NodeData
- parent).</emphasis></entry>
- </row>
-
- <row>
- <entry>listChildPropertiesData</entry>
-
- <entry>This is the alias for the method
- <emphasis>listChildPropertiesData(NodeData
- parent).</emphasis></entry>
- </row>
-
- <row>
- <entry>getReferencesData</entry>
-
- <entry>This is the alias for the method
- <emphasis>getReferencesData(String
- nodeIdentifier).</emphasis></entry>
- </row>
-
- <row>
- <entry>commit</entry>
-
- <entry>This is the alias for the method
- <emphasis>commit().</emphasis></entry>
- </row>
-
- <row>
- <entry>addNodeData</entry>
-
- <entry>This is the alias for the method <emphasis>add(NodeData
- data).</emphasis></entry>
- </row>
-
- <row>
- <entry>addPropertyData</entry>
-
- <entry>This is the alias for the method <emphasis>add(PropertyData
- data).</emphasis></entry>
- </row>
-
- <row>
- <entry>updateNodeData</entry>
-
- <entry>This is the alias for the method <emphasis>update(NodeData
- data).</emphasis></entry>
- </row>
-
- <row>
- <entry>updatePropertyData</entry>
-
- <entry>This is the alias for the method
- <emphasis>update(PropertyData data).</emphasis></entry>
- </row>
-
- <row>
- <entry>deleteNodeData</entry>
-
- <entry>This is the alias for the method <emphasis>delete(NodeData
- data).</emphasis></entry>
- </row>
-
- <row>
- <entry>deletePropertyData</entry>
-
- <entry>This is the alias for the method
- <emphasis>delete(PropertyData data).</emphasis></entry>
- </row>
-
- <row>
- <entry>renameNodeData</entry>
-
- <entry>This is the alias for the method <emphasis>rename(NodeData
- data).</emphasis></entry>
- </row>
-
- <row>
- <entry>rollback</entry>
-
- <entry>This is the alias for the method
- <emphasis>rollback().</emphasis></entry>
- </row>
-
- <row>
- <entry>isOpened</entry>
-
- <entry>This is the alias for the method
- <emphasis>isOpened().</emphasis></entry>
- </row>
-
- <row>
- <entry>close</entry>
-
- <entry>This is the alias for the method
- <emphasis>close().</emphasis></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table>
- <title>Metric Alias</title>
-
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>Min</entry>
-
- <entry>The minimum time spent into the method.</entry>
- </row>
-
- <row>
- <entry>Max</entry>
-
- <entry>The maximum time spent into the method.</entry>
- </row>
-
- <row>
- <entry>Total</entry>
-
- <entry>The total amount of time spent into the method.</entry>
- </row>
-
- <row>
- <entry>Avg</entry>
-
- <entry>The average time spent into the method.</entry>
- </row>
-
- <row>
- <entry>Times</entry>
-
- <entry>The total amount of times the method has been
- called.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="ch_statistics">
+ <?dbhtml filename="ch-statistics"?>
+
+ <title>eXo JCR statistics</title>
+
+ <section>
+ <title>Statistics on the Database Access Layer</title>
+
+ <para>In order to have a better idea of the time spent into the database
+ access layer, it cans be interesting to get some statistics on that part
+ of the code, knowing that most of the time spent into eXo JCR is mainly
+ the database access. This statistics will then allow you to identify
+ without using any profiler what is anormally slow in this layer, which
+ could help to fix the problem quickly.</para>
+
+ <para>In case you use
+ <envar>org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer</envar>
+ or
+ <envar>org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer</envar>
+ as <envar>WorkspaceDataContainer</envar>, you can get statistics on the
+ time spent into the database access layer. The database access layer (in
+ eXo JCR) is represented by the methods of the interface
+ <envar>org.exoplatform.services.jcr.storage.WorkspaceStorageConnection</envar>,
+ so for all the methods defined in this interface, we can have the
+ following figures:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The minimum time spent into the method.</para>
+ </listitem>
+
+ <listitem>
+ <para>The maximum time spent into the method.</para>
+ </listitem>
+
+ <listitem>
+ <para>The average time spent into the method.</para>
+ </listitem>
+
+ <listitem>
+ <para>The total amount of time spent into the method.</para>
+ </listitem>
+
+ <listitem>
+ <para>The total amount of times the method has been called.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Those figures are also available globaly for all the methods which
+ gives us the global behavior of this layer.</para>
+
+ <para>If you want to enable the statistics, you just need to set the JVM
+ parameter called
+ <emphasis>JDBCWorkspaceDataContainer.statistics.enabled</emphasis> to
+ <emphasis>true</emphasis>. The corresponding CSV file is
+ <emphasis>StatisticsJDBCStorageConnection-${creation-timestamp}.csv</emphasis>
+ for more details about how the csv files are managed please refer to the
+ section dedicated to the statistics manager.</para>
+
+ <para>The format of each column header is ${method-alias}-${metric-alias}.
+ The metric alias are described in the statistics manager section.</para>
+
+ <table>
+ <title>Method Alias</title>
+
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>global</entry>
+
+ <entry>This is the alias for all the methods.</entry>
+ </row>
+
+ <row>
+ <entry>getItemDataById</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getItemData(String identifier).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>getItemDataByNodeDataNQPathEntry</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getItemData(NodeData parentData, QPathEntry
+ name).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>getChildNodesData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getChildNodesData(NodeData parent).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>getChildNodesCount</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getChildNodesCount(NodeData parent).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>getChildPropertiesData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getChildPropertiesData(NodeData
+ parent).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>listChildPropertiesData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>listChildPropertiesData(NodeData
+ parent).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>getReferencesData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>getReferencesData(String
+ nodeIdentifier).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>commit</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>commit().</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>addNodeData</entry>
+
+ <entry>This is the alias for the method <emphasis>add(NodeData
+ data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>addPropertyData</entry>
+
+ <entry>This is the alias for the method <emphasis>add(PropertyData
+ data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>updateNodeData</entry>
+
+ <entry>This is the alias for the method <emphasis>update(NodeData
+ data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>updatePropertyData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>update(PropertyData data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>deleteNodeData</entry>
+
+ <entry>This is the alias for the method <emphasis>delete(NodeData
+ data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>deletePropertyData</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>delete(PropertyData data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>renameNodeData</entry>
+
+ <entry>This is the alias for the method <emphasis>rename(NodeData
+ data).</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>rollback</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>rollback().</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>isOpened</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>isOpened().</emphasis></entry>
+ </row>
+
+ <row>
+ <entry>close</entry>
+
+ <entry>This is the alias for the method
+ <emphasis>close().</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section>
+ <title>Statistics on the JCR API accesses</title>
+
+ <para>In order to know exactly how your application uses eXo JCR, it cans
+ be interesting to register all the JCR API accesses in order to easily
+ create real life test scenario based on pure JCR calls and also to tune
+ your eXo JCR to better fit your requirements. </para>
+
+ <para>In order to allow you to specify into the configuration which part
+ of eXo JCR needs to be monitored whitout applying any changes in your code
+ and/or building anything, we choosed to rely on the Load-time Weaving
+ proposed by AspectJ.</para>
+
+ <para>To enable this feature, you will have to add in your classpath the
+ following jar files:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>exo.jcr.component.statistics-X.Y.Z</emphasis>.jar
+ corresponding to your eXo JCR version that you can get from the jboss
+ maven repository <ulink
+ url="???"><uri>http://repository.jboss.com/maven2/org/exoplatform/jcr/exo.jcr.component....</uri></ulink>.</para>
+ </listitem>
+
+ <listitem>
+ <para>aspectjrt-1.6.8.jar that you can get from the main maven
+ repository <ulink
+ url="???"><uri>http://repo2.maven.org/maven2/org/aspectj/aspectjrt</uri></ulink>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You will also need to get aspectjweaver-1.6.8.jar from the main
+ maven repository <ulink
+ url="???">http://repo2.maven.org/maven2/org/aspectj/aspectjweaver</ulink>.
+ At this stage, to enable the statistics on the JCR API accesses, you will
+ need to add the JVM parameter
+ <emphasis>-javaagent:${pathto}/aspectjweaver-1.6.8.jar</emphasis> to your
+ command line, for more details please refer to <ulink
+ url="???">http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html</ulink>.</para>
+
+ <para>By default, the configuration will collect statistcs on all the
+ methods of the internal interfaces
+ <emphasis>org.exoplatform.services.jcr.core.ExtendedSession</emphasis>,
+ <emphasis>org.exoplatform.services.jcr.core.ExtendedNode</emphasis> and
+ <emphasis>org.exoplatform.services.jcr.core.ExtendedProperty</emphasis>.
+ To add and/or remove some interfaces to monitor, you have two
+ configuration files to change that are bundled into the jar
+ <emphasis>exo.jcr.component.statistics-X.Y.Z</emphasis>.jar, which are
+ <emphasis>conf/configuration.xml</emphasis> and
+ <emphasis>META-INF/aop.xml</emphasis>.</para>
+
+ <para>The file content below is the content of
+ <emphasis>conf/configuration.xml</emphasis> that you will need to modify
+ to add and/or remove the full qualified name of the interface to monitor,
+ into the list of value parameters of the init param called
+ <emphasis>targetInterfaces</emphasis>.</para>
+
+ <programlisting><configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+
+ <component>
+ <type>org.exoplatform.services.jcr.statistics.JCRAPIAspectConfig</type>
+ <init-params>
+ <values-param>
+ <name>targetInterfaces</name>
+ <value>org.exoplatform.services.jcr.core.ExtendedSession</value>
+ <value>org.exoplatform.services.jcr.core.ExtendedNode</value>
+ <value>org.exoplatform.services.jcr.core.ExtendedProperty</value>
+ </values-param>
+ </init-params>
+ </component>
+</configuration></programlisting>
+
+ <para>The file content below is the content of
+ <emphasis>META-INF/aop.xml</emphasis> that you will to need to modify to
+ add and/or remove the full qualified name of the interface to monitor,
+ into the expression filter of the pointcut called
+ <emphasis>JCRAPIPointcut</emphasis>. As you can see below, by default only
+ JCR API calls from the exoplatform packages are took into account, don't
+ hesistate to modify also this filter to add your own package names.
+ </para>
+
+ <programlisting><aspectj>
+ <aspects>
+ <concrete-aspect name="org.exoplatform.services.jcr.statistics.JCRAPIAspectImpl" extends="org.exoplatform.services.jcr.statistics.JCRAPIAspect">
+ <pointcut name="JCRAPIPointcut"
+ expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(org.exoplatform.services.jcr.core.ExtendedProperty)) &amp;&amp; call(public * *(..))" />
+ </concrete-aspect>
+ </aspects>
+ <weaver>
+ <include within="org.exoplatform..*" />
+ </weaver>
+</aspectj> </programlisting>
+
+ <para>The corresponding CSV files are of type
+ <emphasis>Statistics${interface-name}-${creation-timestamp}.csv</emphasis>
+ for more details about how the csv files are managed please refer to the
+ section dedicated to the statistics manager.</para>
+
+ <para>The format of each column header is ${method-alias}-${metric-alias}.
+ The method alias will be of type ${method-name}(list of parameter types
+ separeted by ; to be compatible with the CSV format).</para>
+
+ <para>The metric alias are described in the statistics manager
+ section.</para>
+
+ <remark>Please note that this feature will affect the performances of eXo
+ JCR so it must be used with caution.</remark>
+ </section>
+
+ <section>
+ <title>Statistics Manager</title>
+
+ <para>The statistics manager manages all the statistics provided by eXo
+ JCR, it is responsible of printing the data into the CSV files but also to
+ expose the statistics through JMX and/or Rest.</para>
+
+ <para>The statistics manager will create all the CSV files for each
+ category of statistics that it manages, the format of those files is
+ <emphasis>Statistics${category-name}-${creation-timestamp}.csv</emphasis>.
+ Those files will be created into the user directory if it is possible
+ otherwise it will create them into the temporary directory. The format of
+ those files is <envar>CSV</envar> (i.e. Comma-Seperated Values), one new
+ line will be added regularily (every 5 seconds by default) and one last
+ line will be added at JVM exit. Each line, will be composed of the 5
+ figures described below for each method and globaly for all the
+ methods.</para>
+
+ <para>See below the description of each metric type:</para>
+
+ <para><table>
+ <title>Metric Alias</title>
+
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>Min</entry>
+
+ <entry>The minimum time spent into the method.</entry>
+ </row>
+
+ <row>
+ <entry>Max</entry>
+
+ <entry>The maximum time spent into the method.</entry>
+ </row>
+
+ <row>
+ <entry>Total</entry>
+
+ <entry>The total amount of time spent into the method.</entry>
+ </row>
+
+ <row>
+ <entry>Avg</entry>
+
+ <entry>The average time spent into the method.</entry>
+ </row>
+
+ <row>
+ <entry>Times</entry>
+
+ <entry>The total amount of times the method has been
+ called.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>You can disable the persistence of the statistics by setting the
+ JVM parameter called
+ <emphasis>JCRStatisticsManager.persistence.enabled</emphasis> to
+ <emphasis>false</emphasis>, by default it is set to
+ <emphasis>true</emphasis>. You can aslo define the period of time between
+ each record (i.e. line of data into the file) by setting the JVM parameter
+ called <emphasis>JCRStatisticsManager.persistence.timeout</emphasis> to
+ your expected value expressed in milliseconds, by default it is set to
+ <emphasis>5000</emphasis>.</para>
+
+ <para>You can also access to the statistics thanks to JMX, the available
+ methods are the following:</para>
+
+ <para><table>
+ <title>JMX Methods</title>
+
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>getMin</entry>
+
+ <entry>Gives the minimum time spent into the method
+ corresponding to the given category name and statistics name.
+ The expected arguments are the name of the category of the
+ statistics (e.g. JDBCStorageConnection) and the name of the
+ expected method or global for the global value.</entry>
+ </row>
+
+ <row>
+ <entry>getMax</entry>
+
+ <entry>Gives the maximum time spent into the method
+ corresponding to the given category name and statistics name.
+ The expected arguments are the name of the category of the
+ statistics (e.g. JDBCStorageConnection) and the name of the
+ expected method or global for the global value.</entry>
+ </row>
+
+ <row>
+ <entry>getTotal</entry>
+
+ <entry>Gives the total amount of time spent into the method
+ corresponding to the given category name and statistics name.
+ The expected arguments are the name of the category of the
+ statistics (e.g. JDBCStorageConnection) and the name of the
+ expected method or global for the global value.</entry>
+ </row>
+
+ <row>
+ <entry>getAvg</entry>
+
+ <entry>Gives the average time spent into the method
+ corresponding to the given category name and statistics name.
+ The expected arguments are the name of the category of the
+ statistics (e.g. JDBCStorageConnection) and the name of the
+ expected method or global for the global value.</entry>
+ </row>
+
+ <row>
+ <entry>getTimes</entry>
+
+ <entry>Gives the total amount of times the method has been
+ called corresponding to the given category name and statistics
+ name. The expected arguments are the name of the category of the
+ statistics (e.g. JDBCStorageConnection) and the name of the
+ expected method or global for the global value.</entry>
+ </row>
+
+ <row>
+ <entry>reset</entry>
+
+ <entry>Reset the statistics for the given category name and
+ statistics name. The expected arguments are the name of the
+ category of the statistics (e.g. JDBCStorageConnection) and the
+ name of the expected method or global for the global
+ value.</entry>
+ </row>
+
+ <row>
+ <entry>resetAll</entry>
+
+ <entry>Reset all the statistics for the given category name. The
+ expected argument is the name of the category of the statistics
+ (e.g. JDBCStorageConnection).</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>The full name of the related MBean is
+ <emphasis>exo:service=statistic, view=jcr</emphasis>.</para>
+ </section>
+</chapter>
16 years
exo-jcr SVN: r2269 - in jcr/trunk: exo.jcr.component.statistics and 11 other directories.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 03:42:49 -0400 (Tue, 13 Apr 2010)
New Revision: 2269
Added:
jcr/trunk/exo.jcr.component.statistics/
jcr/trunk/exo.jcr.component.statistics/pom.xml
jcr/trunk/exo.jcr.component.statistics/src/
jcr/trunk/exo.jcr.component.statistics/src/main/
jcr/trunk/exo.jcr.component.statistics/src/main/java/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspect.java
jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspectConfig.java
jcr/trunk/exo.jcr.component.statistics/src/main/resources/
jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/
jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml
jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/
jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml
Modified:
jcr/trunk/pom.xml
Log:
EXOJCR-611: Implementation based on the Load-time Weaving from AspectJ
Added: jcr/trunk/exo.jcr.component.statistics/pom.xml
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/pom.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.statistics/pom.xml 2010-04-13 07:42:49 UTC (rev 2269)
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (C) 2009 eXo Platform SAS.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software 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 software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.exoplatform.jcr</groupId>
+ <artifactId>jcr-parent</artifactId>
+ <version>1.12.1-GA-SNAPSHOT</version>
+ </parent>
+ <artifactId>exo.jcr.component.statistics</artifactId>
+ <name>eXo JCR :: Component :: Statistics Provider</name>
+ <description>eXo JCR Statistics</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.exoplatform.jcr</groupId>
+ <artifactId>exo.jcr.component.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>aspectj-maven-plugin</artifactId>
+ <version>1.3</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
Added: jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspect.java
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspect.java (rev 0)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspect.java 2010-04-13 07:42:49 UTC (rev 2269)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.statistics;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * This aspect is used to collect all the statistics of all the methods of the JCR API.
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 26 mars 2010
+ */
+@Aspect
+public abstract class JCRAPIAspect
+{
+
+ /**
+ * The logger
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.statistics.JCRAPIAspectC");
+
+ /**
+ * The result of the mapping if the corresponding value cannot be found.
+ */
+ private static final Statistics UNKNOWN = new Statistics(null, "?");
+
+ /**
+ * The flag that indicates if the aspect is initialized or not.
+ */
+ private static volatile boolean INITIALIZED;
+
+ /**
+ * The list of all the interfaces for which we want statistics
+ */
+ private static Class<?>[] TARGET_INTERFACES;
+
+ /**
+ * The mapping between the AspectJ signature and the target statistics
+ */
+ private static volatile Map<String, Statistics> MAPPING = Collections.unmodifiableMap(new HashMap<String, Statistics>());
+
+ /**
+ * The list of all the statistics, one per method
+ */
+ private final static Map<String, Map<String, Statistics>> ALL_STATISTICS = new HashMap<String, Map<String, Statistics>>();
+
+ /**
+ * Gives the name of the statistics from the given {@link Method}
+ */
+ private static String getStatisticsName(Method m)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(m.getName());
+ sb.append('(');
+ Class<?>[] types = m.getParameterTypes();
+ if (types != null)
+ {
+ boolean first = true;
+ for (Class<?> type : types)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ sb.append(", ");
+ }
+ sb.append(type.getSimpleName());
+ }
+ }
+ sb.append(')');
+ return sb.toString();
+ }
+
+ /**
+ * Gives the corresponding statistics for the given target class and AspectJ signature
+ * @param target the target {@link Class}
+ * @param signature the AspectJ signature
+ * @return the related {@link Statistics} or <code>null</code> if it cannot be found
+ */
+ private static Statistics getStatistics(Class<?> target, String signature)
+ {
+ initIfNeeded();
+ Statistics statistics = MAPPING.get(signature);
+ if (statistics == null)
+ {
+ synchronized (JCRAPIAspect.class)
+ {
+ Class<?> interfaceClass = findInterface(target);
+ if (interfaceClass != null)
+ {
+ Map<String, Statistics> allStatistics = ALL_STATISTICS.get(interfaceClass.getSimpleName());
+ if (allStatistics != null)
+ {
+ int index1 = signature.indexOf('(');
+ int index = signature.substring(0, index1).lastIndexOf('.');
+ String name = signature.substring(index + 1);
+ statistics = allStatistics.get(name);
+ }
+ }
+ if (statistics == null)
+ {
+ statistics = UNKNOWN;
+ }
+ Map<String, Statistics> tempMapping = new HashMap<String, Statistics>(MAPPING);
+ tempMapping.put(signature, statistics);
+ MAPPING = Collections.unmodifiableMap(tempMapping);
+ }
+ }
+ if (statistics == UNKNOWN)
+ {
+ return null;
+ }
+ return statistics;
+ }
+
+ /**
+ * Find the monitored interface from the target {@link Class}
+ * @param target the target {@link Class}
+ * @return the monitored interface, <code>null</code> otherwise
+ */
+ private static Class<?> findInterface(Class<?> target)
+ {
+ if (target == null)
+ {
+ return null;
+ }
+ Class<?>[] interfaces = target.getInterfaces();
+ if (interfaces != null)
+ {
+ for (Class<?> c : TARGET_INTERFACES)
+ {
+ for (Class<?> i : interfaces)
+ {
+ if (c.getName().equals(i.getName()))
+ {
+ return c;
+ }
+ }
+ }
+ }
+ return findInterface(target.getSuperclass());
+ }
+
+ /**
+ * Initializes the aspect if needed
+ */
+ private static void initIfNeeded()
+ {
+ if (!INITIALIZED)
+ {
+ synchronized (JCRAPIAspect.class)
+ {
+ if (!INITIALIZED)
+ {
+ ExoContainer container = ExoContainerContext.getTopContainer();
+ JCRAPIAspectConfig config = null;
+ if (container != null)
+ {
+ config = (JCRAPIAspectConfig)container.getComponentInstanceOfType(JCRAPIAspectConfig.class);
+ }
+ if (config == null)
+ {
+ TARGET_INTERFACES = new Class<?>[]{};
+ LOG.warn("No interface to monitor could be found");
+ }
+ else
+ {
+ TARGET_INTERFACES = config.getTargetInterfaces();
+ for (Class<?> c : TARGET_INTERFACES)
+ {
+ Statistics global = new Statistics(null, "global");
+ Map<String, Statistics> statistics = new TreeMap<String, Statistics>();
+ Method[] methods = c.getMethods();
+ for (Method m : methods)
+ {
+ String name = getStatisticsName(m);
+ statistics.put(name, new Statistics(global, name));
+ }
+ JCRStatisticsManager.registerStatistics(c.getSimpleName(), global, statistics);
+ ALL_STATISTICS.put(c.getSimpleName(), statistics);
+ }
+ }
+ INITIALIZED = true;
+ }
+ }
+ }
+ }
+
+ @Pointcut
+ abstract void JCRAPIPointcut();
+
+ @Before("JCRAPIPointcut()")
+ public void begin(JoinPoint thisJoinPoint)
+ {
+ Statistics statistics =
+ getStatistics(thisJoinPoint.getTarget().getClass(), thisJoinPoint.getSignature().toString());
+ if (statistics != null)
+ {
+ statistics.begin();
+ }
+ }
+
+ @After("JCRAPIPointcut()")
+ public void end(JoinPoint thisJoinPoint)
+ {
+ Statistics statistics =
+ getStatistics(thisJoinPoint.getTarget().getClass(), thisJoinPoint.getSignature().toString());
+ if (statistics != null)
+ {
+ statistics.end();
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspectConfig.java
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspectConfig.java (rev 0)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/java/org/exoplatform/services/jcr/statistics/JCRAPIAspectConfig.java 2010-04-13 07:42:49 UTC (rev 2269)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.statistics;
+
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.container.xml.ValuesParam;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The configuration of the {@link JCRAPIAspect}
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 9 avr. 2010
+ */
+public class JCRAPIAspectConfig
+{
+
+ /**
+ * The logger
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.statistics.JCRAPIAspectConfig");
+
+ /**
+ * The list of interfaces that we want to monitor
+ */
+ private Class<?>[] targetInterfaces;
+
+ /**
+ * Default constructor
+ */
+ public JCRAPIAspectConfig(InitParams params)
+ {
+ this.targetInterfaces = loadTargetInterfaces(params.getValuesParam("targetInterfaces"));
+ }
+
+ /**
+ * @return the list of interfaces to monitor
+ */
+ private Class<?>[] loadTargetInterfaces(ValuesParam params)
+ {
+ ArrayList<?> values = params.getValues();
+ List<Class<?>> lTargetInterfaces = new ArrayList<Class<?>>();
+ if (values != null)
+ {
+ for (Object o : params.getValues())
+ {
+ String className = null;
+ try
+ {
+ className = (String)o;
+ lTargetInterfaces.add(Class.forName(className));
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot find the target interface " + className, e);
+ }
+ }
+ }
+ Class<?>[] targetInterfaces = new Class<?>[lTargetInterfaces.size()];
+ return (Class<?>[])lTargetInterfaces.toArray(targetInterfaces);
+ }
+
+ /**
+ * @return the list of target interfaces
+ */
+ public Class<?>[] getTargetInterfaces()
+ {
+ return targetInterfaces;
+ }
+}
Added: jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/resources/META-INF/aop.xml 2010-04-13 07:42:49 UTC (rev 2269)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="org.exoplatform.services.jcr.statistics.JCRAPIAspectImpl" extends="org.exoplatform.services.jcr.statistics.JCRAPIAspect">
+ <pointcut name="JCRAPIPointcut"
+ expression="(target(org.exoplatform.services.jcr.core.ExtendedSession) || target(org.exoplatform.services.jcr.core.ExtendedNode) || target(org.exoplatform.services.jcr.core.ExtendedProperty)) && call(public * *(..))" />
+ </concrete-aspect>
+ </aspects>
+ <weaver>
+ <include within="org.exoplatform..*" />
+ </weaver>
+</aspectj>
\ No newline at end of file
Added: jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml
===================================================================
--- jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.statistics/src/main/resources/conf/configuration.xml 2010-04-13 07:42:49 UTC (rev 2269)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+ <!--
+
+ Copyright (C) 2009 eXo Platform SAS. This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software 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 software; if not,
+ write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+
+ <component>
+ <type>org.exoplatform.services.jcr.statistics.JCRAPIAspectConfig</type>
+ <init-params>
+ <values-param>
+ <name>targetInterfaces</name>
+ <value>org.exoplatform.services.jcr.core.ExtendedSession</value>
+ <value>org.exoplatform.services.jcr.core.ExtendedNode</value>
+ <value>org.exoplatform.services.jcr.core.ExtendedProperty</value>
+ </values-param>
+ </init-params>
+ </component>
+</configuration>
Modified: jcr/trunk/pom.xml
===================================================================
--- jcr/trunk/pom.xml 2010-04-13 07:03:28 UTC (rev 2268)
+++ jcr/trunk/pom.xml 2010-04-13 07:42:49 UTC (rev 2269)
@@ -360,7 +360,12 @@
<groupId>jboss.jbossts</groupId>
<artifactId>jbossts-common</artifactId>
<version>4.6.1.GA</version>
- </dependency>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ <version>1.6.8</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
@@ -425,7 +430,8 @@
</testResources>
</build>
<modules>
- <module>exo.jcr.component.core</module>
+ <module>exo.jcr.component.core</module>
+ <module>exo.jcr.component.statistics</module>
<module>exo.jcr.component.ext</module>
<module>exo.jcr.component.ftp</module>
<module>exo.jcr.component.webdav</module>
16 years
exo-jcr SVN: r2268 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics and 3 other directories.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2010-04-13 03:03:28 -0400 (Tue, 13 Apr 2010)
New Revision: 2268
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/JCRStatisticsManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/Statistics.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/statistics/
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/statistics/TestJCRStatisticsManager.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
Log:
EXOJCR-611: Provide a way to collect statistics around the JCR API accesses
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2010-04-12 12:47:24 UTC (rev 2267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2010-04-13 07:03:28 UTC (rev 2268)
@@ -1,27 +1,3 @@
-package org.exoplatform.services.jcr.impl.storage.jdbc.statistics;
-
-import org.exoplatform.services.jcr.datamodel.ItemData;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.datamodel.PropertyData;
-import org.exoplatform.services.jcr.datamodel.QPathEntry;
-import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
-import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.RepositoryException;
-
/*
* Copyright (C) 2003-2010 eXo Platform SAS.
*
@@ -38,13 +14,27 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
+package org.exoplatform.services.jcr.impl.storage.jdbc.statistics;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
+import org.exoplatform.services.jcr.statistics.JCRStatisticsManager;
+import org.exoplatform.services.jcr.statistics.Statistics;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.RepositoryException;
+
/**
- * This class is used to give statistics about the time spent in the database access layer. It will
- * print all the metrics value into a file in csv format. It will provide metrics of type
- * minimum, maximum, total, times and average for each method of {@link WorkspaceStorageConnection}
- * and the global values. It will add data into the file every 5 seconds and add the last line at
- * JVM exit. To activate the statistics, set the JVM parameter called
+ * This class is used to give statistics about the time spent in the database access layer.
+ * To activate the statistics, set the JVM parameter called
* "JDBCWorkspaceDataContainer.statistics.enabled" to <code>true</code>.
*
* Created by The eXo Platform SAS
@@ -56,11 +46,6 @@
{
/**
- * The logger
- */
- private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.StatisticsJDBCStorageConnection");
-
- /**
* The description of the statistics corresponding to the method
* <code>update(PropertyData data)</code>
*/
@@ -171,7 +156,7 @@
/**
* The global statistics for all the database accesses
*/
- private final static Statistics GLOBAL_STATISTICS = new Statistics("global");
+ private final static Statistics GLOBAL_STATISTICS = new Statistics(null, "global");
/**
* The list of all the statistics, one per method
@@ -180,126 +165,47 @@
static
{
// Read Methods
- ALL_STATISTICS.put(GET_ITEM_DATA_BY_ID_DESCR, new Statistics(GET_ITEM_DATA_BY_ID_DESCR));
- ALL_STATISTICS.put(GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR, new Statistics(
+ ALL_STATISTICS.put(GET_ITEM_DATA_BY_ID_DESCR, new Statistics(GLOBAL_STATISTICS, GET_ITEM_DATA_BY_ID_DESCR));
+ ALL_STATISTICS.put(GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR, new Statistics(GLOBAL_STATISTICS,
GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR));
- ALL_STATISTICS.put(GET_CHILD_NODES_DATA_DESCR, new Statistics(GET_CHILD_NODES_DATA_DESCR));
- ALL_STATISTICS.put(GET_CHILD_NODES_COUNT_DESCR, new Statistics(GET_CHILD_NODES_COUNT_DESCR));
- ALL_STATISTICS.put(GET_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GET_CHILD_PROPERTIES_DATA_DESCR));
- ALL_STATISTICS.put(LIST_CHILD_PROPERTIES_DATA_DESCR, new Statistics(LIST_CHILD_PROPERTIES_DATA_DESCR));
- ALL_STATISTICS.put(GET_REFERENCES_DATA_DESCR, new Statistics(GET_REFERENCES_DATA_DESCR));
+ ALL_STATISTICS.put(GET_CHILD_NODES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_DATA_DESCR));
+ ALL_STATISTICS.put(GET_CHILD_NODES_COUNT_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_COUNT_DESCR));
+ ALL_STATISTICS.put(GET_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
+ GET_CHILD_PROPERTIES_DATA_DESCR));
+ ALL_STATISTICS.put(LIST_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
+ LIST_CHILD_PROPERTIES_DATA_DESCR));
+ ALL_STATISTICS.put(GET_REFERENCES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, GET_REFERENCES_DATA_DESCR));
// Write Methods
// Commit
- ALL_STATISTICS.put(COMMIT_DESCR, new Statistics(COMMIT_DESCR));
+ ALL_STATISTICS.put(COMMIT_DESCR, new Statistics(GLOBAL_STATISTICS, COMMIT_DESCR));
// Add methods
- ALL_STATISTICS.put(ADD_NODE_DATA_DESCR, new Statistics(ADD_NODE_DATA_DESCR));
- ALL_STATISTICS.put(ADD_PROPERTY_DATA_DESCR, new Statistics(ADD_PROPERTY_DATA_DESCR));
+ ALL_STATISTICS.put(ADD_NODE_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, ADD_NODE_DATA_DESCR));
+ ALL_STATISTICS.put(ADD_PROPERTY_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, ADD_PROPERTY_DATA_DESCR));
// Update methods
- ALL_STATISTICS.put(UPDATE_NODE_DATA_DESCR, new Statistics(UPDATE_NODE_DATA_DESCR));
- ALL_STATISTICS.put(UPDATE_PROPERTY_DATA_DESCR, new Statistics(UPDATE_PROPERTY_DATA_DESCR));
+ ALL_STATISTICS.put(UPDATE_NODE_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, UPDATE_NODE_DATA_DESCR));
+ ALL_STATISTICS.put(UPDATE_PROPERTY_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, UPDATE_PROPERTY_DATA_DESCR));
// Delete methods
- ALL_STATISTICS.put(DELETE_NODE_DATA_DESCR, new Statistics(DELETE_NODE_DATA_DESCR));
- ALL_STATISTICS.put(DELETE_PROPERTY_DATA_DESCR, new Statistics(DELETE_PROPERTY_DATA_DESCR));
+ ALL_STATISTICS.put(DELETE_NODE_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, DELETE_NODE_DATA_DESCR));
+ ALL_STATISTICS.put(DELETE_PROPERTY_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, DELETE_PROPERTY_DATA_DESCR));
// Rename
- ALL_STATISTICS.put(RENAME_NODE_DATA_DESCR, new Statistics(RENAME_NODE_DATA_DESCR));
+ ALL_STATISTICS.put(RENAME_NODE_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, RENAME_NODE_DATA_DESCR));
// Rollback
- ALL_STATISTICS.put(ROLLBACK_DESCR, new Statistics(ROLLBACK_DESCR));
+ ALL_STATISTICS.put(ROLLBACK_DESCR, new Statistics(GLOBAL_STATISTICS, ROLLBACK_DESCR));
// Others
- ALL_STATISTICS.put(IS_OPENED_DESCR, new Statistics(IS_OPENED_DESCR));
- ALL_STATISTICS.put(CLOSE_DESCR, new Statistics(CLOSE_DESCR));
+ ALL_STATISTICS.put(IS_OPENED_DESCR, new Statistics(null, IS_OPENED_DESCR));
+ ALL_STATISTICS.put(CLOSE_DESCR, new Statistics(null, CLOSE_DESCR));
}
- /**
- * The printer used to print the statistics in csv format
- */
- private static PrintWriter STATISTICS_WRITER;
static
{
if (JDBCWorkspaceDataContainer.STATISTICS_ENABLED)
{
- initWriter();
- if (STATISTICS_WRITER != null)
- {
- addTriggers();
- }
+ JCRStatisticsManager.registerStatistics("JDBCStorageConnection", GLOBAL_STATISTICS, ALL_STATISTICS);
}
}
- /**
- * Add all the triggers that will keep the file up to date.
- */
- private static void addTriggers()
- {
- Runtime.getRuntime().addShutdownHook(new Thread("StatisticsJDBCStorageConnection-Hook")
- {
- public void run()
- {
- printData();
- }
- });
- // Define the file header
- printHeader();
- Thread t = new Thread("StatisticsJDBCStorageConnection-Writer")
- {
- public void run()
- {
- while (true)
- {
- try
- {
- sleep(5000);
- }
- catch (InterruptedException e)
- {
- LOG.debug("InterruptedException", e);
- }
- printData();
- }
- }
- };
- t.setDaemon(true);
- t.start();
- }
/**
- * Initialize the {@link PrintWriter}.
- * It will first try to create the file in the user directory, if it cannot, it will try
- * to create it in the temporary folder.
- */
- private static void initWriter()
- {
- File file = null;
- try
- {
- file =
- new File(System.getProperty("user.dir"), "StatisticsJDBCStorageConnection-" + System.currentTimeMillis()
- + ".csv");
- file.createNewFile();
- STATISTICS_WRITER = new PrintWriter(file);
- }
- catch (IOException e)
- {
- LOG
- .error(
- "Cannot create the file for the statistics in the user directory, we will try to create it in the temp directory",
- e);
- try
- {
- file = File.createTempFile("StatisticsJDBCStorageConnection", "-" + System.currentTimeMillis() + ".csv");
- STATISTICS_WRITER = new PrintWriter(file);
- }
- catch (IOException e1)
- {
- LOG.error("Cannot create the file for the statistics", e1);
- }
- }
- if (file != null)
- {
- LOG.info("The file for the statistics is " + file.getPath());
- }
- }
-
- /**
* The nested {@link WorkspaceStorageConnection}
*/
private final WorkspaceStorageConnection wcs;
@@ -633,173 +539,4 @@
s.end();
}
}
-
- /**
- * Print the header of the csv file
- */
- private static void printHeader()
- {
- GLOBAL_STATISTICS.printHeader(STATISTICS_WRITER);
- for (Statistics s : ALL_STATISTICS.values())
- {
- STATISTICS_WRITER.print(',');
- s.printHeader(STATISTICS_WRITER);
- }
- STATISTICS_WRITER.println();
- STATISTICS_WRITER.flush();
- }
-
- /**
- * Add one line of data
- */
- private static void printData()
- {
- GLOBAL_STATISTICS.printData(STATISTICS_WRITER);
- for (Statistics s : ALL_STATISTICS.values())
- {
- STATISTICS_WRITER.print(',');
- s.printData(STATISTICS_WRITER);
- }
- STATISTICS_WRITER.println();
- STATISTICS_WRITER.flush();
- }
-
- /**
- * The class used to manage all the metrics such as minimum, maximum, total, times and average.
- */
- private static class Statistics
- {
-
- /**
- * The description of the statistics
- */
- private final String description;
-
- /**
- * The min value of the time spent for one call
- */
- private final AtomicLong min = new AtomicLong(Long.MAX_VALUE);
-
- /**
- * The max value of the time spent for one call
- */
- private final AtomicLong max = new AtomicLong(-1);
-
- /**
- * The total time spent for all the calls
- */
- private final AtomicLong total = new AtomicLong();
-
- /**
- * The total amount of calls
- */
- private final AtomicLong times = new AtomicLong();
-
- /**
- * The {@link ThreadLocal} used to keep the initial timestamp
- */
- private final ThreadLocal<Queue<Long>> currentTime = new ThreadLocal<Queue<Long>>()
- {
- protected Queue<Long> initialValue()
- {
- return new LinkedList<Long>();
- }
- };
-
- /**
- * The default constructor
- * @param description the description of the statistics
- */
- public Statistics(String description)
- {
- this.description = description;
- }
-
- /**
- * Start recording
- */
- public void begin()
- {
- GLOBAL_STATISTICS.onBegin();
- onBegin();
- }
-
- /**
- * Store the current timestamp in the {@link ThreadLocal}
- */
- private void onBegin()
- {
- Queue<Long> q = currentTime.get();
- q.add(System.currentTimeMillis());
- }
-
- /**
- * Stop recording
- */
- public void end()
- {
- onEnd();
- GLOBAL_STATISTICS.onEnd();
- }
-
- /**
- * Refresh the values of the metrics (min, max, total and times)
- */
- private void onEnd()
- {
- long result = System.currentTimeMillis() - currentTime.get().poll();
- times.incrementAndGet();
- if (result < min.get())
- {
- min.set(result);
- }
- if (max.get() < result)
- {
- max.set(result);
- }
- total.addAndGet(result);
- }
-
- /**
- * Print the description of all the metrics into the given {@link PrintWriter}
- */
- public void printHeader(PrintWriter pw)
- {
- pw.print(description);
- pw.print("-Min,");
- pw.print(description);
- pw.print("-Max,");
- pw.print(description);
- pw.print("-Total,");
- pw.print(description);
- pw.print("-Avg,");
- pw.print(description);
- pw.print("-Times");
- }
-
- /**
- * Print the current snapshot of the metrics and evaluate the average value
- */
- public void printData(PrintWriter pw)
- {
- long lmin = min.get();
- if (lmin == Long.MAX_VALUE)
- {
- lmin = -1;
- }
- long lmax = max.get();
- long ltotal = total.get();
- long ltimes = times.get();
- float favg = ltimes == 0 ? 0f : (float)ltotal / ltimes;
- pw.print(lmin);
- pw.print(',');
- pw.print(lmax);
- pw.print(',');
- pw.print(ltotal);
- pw.print(',');
- pw.print(favg);
- pw.print(',');
- pw.print(ltimes);
- }
- }
}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/JCRStatisticsManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/JCRStatisticsManager.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/JCRStatisticsManager.java 2010-04-13 07:03:28 UTC (rev 2268)
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.statistics;
+
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.management.ManagementContext;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.management.jmx.annotations.Property;
+import org.exoplatform.management.rest.annotations.RESTEndpoint;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class manages all the statistics of eXo JCR. This will print all the metrics value into a file in csv format
+ * for all the registered statistics. It will provide metrics of type minimum, maximum, total, times and average
+ * for each method of {@link WorkspaceStorageConnection} and the global values. It will add data into the file
+ * every 5 seconds and add the last line at JVM exit. This class will also expose all the statistics through JMX.
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 30 mars 2010
+ */
+@Managed
+@ManagedDescription("JCR statistics manager")
+@NameTemplate({@Property(key = "view", value = "jcr"), @Property(key = "service", value = "statistic")})
+@RESTEndpoint(path = "jcrstatistics")
+public class JCRStatisticsManager
+{
+
+ /**
+ * The logger
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.JCRStatisticsManager");
+
+ /**
+ * The name of the global statistics
+ */
+ private static final String GLOBAL_STATISTICS_NAME = "global";
+
+ /**
+ * The flag that indicates if the manager is launched or not.
+ */
+ private static volatile boolean STARTED;
+
+ /**
+ * The list of all the contexts of statistics managed
+ */
+ private static Map<String, StatisticsContext> CONTEXTS =
+ Collections.unmodifiableMap(new HashMap<String, StatisticsContext>());
+
+ /**
+ * Indicates if the persistence of the statistics has to be enabled.
+ */
+ public static final boolean PERSISTENCE_ENABLED =
+ Boolean.valueOf(System.getProperty("JCRStatisticsManager.persistence.enabled", "true"));
+
+ /**
+ * The length of time in milliseconds after which the snapshot of the statistics is persisted.
+ */
+ public static final long PERSISTENCE_TIMEOUT =
+ Long.valueOf(System.getProperty("JCRStatisticsManager.persistence.timeout", "5000"));
+
+ /**
+ * Default constructor.
+ */
+ private JCRStatisticsManager()
+ {
+ }
+
+ /**
+ * Register a new category of statistics to manage.
+ * @param category the name of the category of statistics to register.
+ * @param global the global statistics.
+ * @param allStatistics the list of all statistics corresponding to the category.
+ */
+ public static void registerStatistics(String category, Statistics global, Map<String, Statistics> allStatistics)
+ {
+ if (category == null || category.length() == 0)
+ {
+ throw new IllegalArgumentException("The category of the statistics cannot be empty");
+ }
+ if (allStatistics == null || allStatistics.isEmpty())
+ {
+ throw new IllegalArgumentException("The list of statistics " + category + " cannot be empty");
+ }
+ PrintWriter pw = null;
+ if (PERSISTENCE_ENABLED)
+ {
+ pw = initWriter(category);
+ if (pw == null)
+ {
+ LOG.warn("Cannot create the print writer for the statistics " + category);
+ }
+ }
+ startIfNeeded();
+ synchronized (JCRStatisticsManager.class)
+ {
+ Map<String, StatisticsContext> tmpContexts = new HashMap<String, StatisticsContext>(CONTEXTS);
+ StatisticsContext ctx = new StatisticsContext(pw, global, allStatistics);
+ tmpContexts.put(category, ctx);
+ if (pw != null)
+ {
+ // Define the file header
+ printHeader(ctx);
+ }
+ CONTEXTS = Collections.unmodifiableMap(tmpContexts);
+ }
+ }
+
+ /**
+ * Initialize the {@link PrintWriter}.
+ * It will first try to create the file in the user directory, if it cannot, it will try
+ * to create it in the temporary folder.
+ * @return the corresponding {@link PrintWriter}
+ */
+ private static PrintWriter initWriter(String category)
+ {
+ PrintWriter pw = null;
+ File file = null;
+ try
+ {
+ file =
+ new File(System.getProperty("user.dir"), "Statistics" + category + "-" + System.currentTimeMillis()
+ + ".csv");
+ file.createNewFile();
+ pw = new PrintWriter(file);
+ }
+ catch (IOException e)
+ {
+ LOG.error("Cannot create the file for the statistics " + category
+ + " in the user directory, we will try to create it in the temp directory", e);
+ try
+ {
+ file = File.createTempFile("Statistics" + category, "-" + System.currentTimeMillis() + ".csv");
+ pw = new PrintWriter(file);
+ }
+ catch (IOException e1)
+ {
+ LOG.error("Cannot create the file for the statistics " + category, e1);
+ }
+ }
+ if (file != null)
+ {
+ LOG.info("The file for the statistics " + category + " is " + file.getPath());
+ }
+ return pw;
+ }
+
+ /**
+ * Starts the manager if needed
+ */
+ private static void startIfNeeded()
+ {
+ if (!STARTED)
+ {
+ synchronized (JCRStatisticsManager.class)
+ {
+ if (!STARTED)
+ {
+ addTriggers();
+ ExoContainer container = ExoContainerContext.getTopContainer();
+ ManagementContext ctx = null;
+ if (container != null)
+ {
+ ctx = container.getManagementContext();
+ }
+ if (ctx == null)
+ {
+ LOG.warn("Cannot register the statistics");
+ }
+ else
+ {
+ ctx.register(new JCRStatisticsManager());
+ }
+ STARTED = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Add all the triggers that will keep the file up to date only if the persistence
+ * is enabled.
+ */
+ private static void addTriggers()
+ {
+ if (!PERSISTENCE_ENABLED)
+ {
+ return;
+ }
+ Runtime.getRuntime().addShutdownHook(new Thread("JCRStatisticsManager-Hook")
+ {
+ public void run()
+ {
+ printData();
+ }
+ });
+ Thread t = new Thread("JCRStatisticsManager-Writer")
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ sleep(PERSISTENCE_TIMEOUT);
+ }
+ catch (InterruptedException e)
+ {
+ LOG.debug("InterruptedException", e);
+ }
+ printData();
+ }
+ }
+ };
+ t.setDaemon(true);
+ t.start();
+ }
+
+ /**
+ * Print the header of the csv file related to the given context.
+ */
+ private static void printHeader(StatisticsContext context)
+ {
+ if (context.writer == null)
+ {
+ return;
+ }
+ boolean first = true;
+ if (context.global != null)
+ {
+ context.global.printHeader(context.writer);
+ first = false;
+ }
+ for (Statistics s : context.allStatistics.values())
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ context.writer.print(',');
+ }
+ s.printHeader(context.writer);
+ }
+ context.writer.println();
+ context.writer.flush();
+ }
+
+ /**
+ * Add one line of data to all the csv files.
+ */
+ private static void printData()
+ {
+ Map<String, StatisticsContext> tmpContexts = CONTEXTS;
+ for (StatisticsContext context : tmpContexts.values())
+ {
+ printData(context);
+ }
+ }
+
+ /**
+ * Add one line of data to the csv file related to the given context.
+ */
+ private static void printData(StatisticsContext context)
+ {
+ if (context.writer == null)
+ {
+ return;
+ }
+ boolean first = true;
+ if (context.global != null)
+ {
+ context.global.printData(context.writer);
+ first = false;
+ }
+ for (Statistics s : context.allStatistics.values())
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ context.writer.print(',');
+ }
+ s.printData(context.writer);
+ }
+ context.writer.println();
+ context.writer.flush();
+ }
+
+ /**
+ * Retrieve statistics context of the given category.
+ * @return the related {@link StatisticsContext}, <code>null</code> otherwise.
+ */
+ private static StatisticsContext getContext(String category)
+ {
+ if (category == null)
+ {
+ return null;
+ }
+ return CONTEXTS.get(category);
+ }
+
+ /**
+ * Format the name of the statistics in the target format
+ * @param name the name of the statistics requested
+ * @return the formated statistics name
+ */
+ static String formatName(String name)
+ {
+ return name == null ? null : name.replaceAll(" ", "").replaceAll("[,;]", ", ");
+ }
+
+ /**
+ * Retrieve statistics of the given category and name.
+ * @return the related {@link Statistics}, <code>null</code> otherwise.
+ */
+ private static Statistics getStatistics(String category, String name)
+ {
+ StatisticsContext context = getContext(category);
+ if (context == null)
+ {
+ return null;
+ }
+ // Format the name
+ name = formatName(name);
+ if (name == null)
+ {
+ return null;
+ }
+ Statistics statistics;
+ if (GLOBAL_STATISTICS_NAME.equalsIgnoreCase(name))
+ {
+ statistics = context.global;
+ }
+ else
+ {
+ statistics = context.allStatistics.get(name);
+ }
+ return statistics;
+ }
+
+ /**
+ * @return the <code>min</code> value for the statistics corresponding to the given
+ * category and name.
+ */
+ @Managed
+ @ManagedDescription("The minimum value of the time spent for one call.")
+ public static long getMin(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ return statistics == null ? 0l : statistics.getMin();
+ }
+
+ /**
+ * @return the <code>max</code> value for the statistics corresponding to the given
+ * category and name.
+ */
+ @Managed
+ @ManagedDescription("The maximum value of the time spent for one call.")
+ public static long getMax(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ return statistics == null ? 0l : statistics.getMax();
+ }
+
+ /**
+ * @return the <code>total</code> value for the statistics corresponding to the given
+ * category and name.
+ */
+ @Managed
+ @ManagedDescription("The total time spent for all the calls.")
+ public static long getTotal(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ return statistics == null ? 0l : statistics.getTotal();
+ }
+
+ /**
+ * @return the <code>times</code> value for the statistics corresponding to the given
+ * category and name.
+ */
+ @Managed
+ @ManagedDescription("The total amount of calls.")
+ public static long getTimes(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ return statistics == null ? 0l : statistics.getTimes();
+ }
+
+ /**
+ * @return the <code>avg</code> value for the statistics corresponding to the given
+ * category and name.
+ */
+ @Managed
+ @ManagedDescription("The average value of the time spent for one call.")
+ public static float getAvg(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ return statistics == null ? 0l : statistics.getAvg();
+ }
+
+ /**
+ * Allows to reset the statistics corresponding to the given category and name.
+ * @param category
+ * @param name
+ */
+ @Managed
+ @ManagedDescription("Reset the statistics.")
+ public static void reset(String category, String name)
+ {
+ Statistics statistics = getStatistics(category, name);
+ if (statistics != null)
+ {
+ statistics.reset();
+ }
+ }
+
+ /**
+ * Allows to reset all the statistics corresponding to the given category.
+ * @param category
+ */
+ @Managed
+ @ManagedDescription("Reset all the statistics.")
+ public static void resetAll(String category)
+ {
+ StatisticsContext context = getContext(category);
+ if (context != null)
+ {
+ context.reset();
+ }
+ }
+
+ /**
+ * Define the context of a given category of statistics
+ */
+ private static class StatisticsContext
+ {
+
+ /**
+ * The printer used to print the statistics in csv format
+ */
+ private final PrintWriter writer;
+
+ /**
+ * The list of all the statistics
+ */
+ private final Map<String, Statistics> allStatistics;
+
+ /**
+ * The global statistics
+ */
+ private final Statistics global;
+
+ /**
+ * The default constructor.
+ */
+ public StatisticsContext(PrintWriter writer, Statistics global, Map<String, Statistics> allStatistics)
+ {
+ this.writer = writer;
+ this.global = global;
+ this.allStatistics = allStatistics;
+ }
+
+ /**
+ * Reset all the statistics related to the given context.
+ */
+ public void reset()
+ {
+ if (global != null)
+ {
+ global.reset();
+ }
+ for (Statistics statistics : allStatistics.values())
+ {
+ statistics.reset();
+ }
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/Statistics.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/Statistics.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/statistics/Statistics.java 2010-04-13 07:03:28 UTC (rev 2268)
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.statistics;
+
+import java.io.PrintWriter;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * The class used to manage all the metrics such as minimum, maximum, total, times and average.
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 30 mars 2010
+ */
+public class Statistics
+{
+
+ /**
+ * The global statistics on the top of the current ones
+ */
+ private final Statistics parent;
+
+ /**
+ * The description of the statistics
+ */
+ private final String description;
+
+ /**
+ * The min value of the time spent for one call
+ */
+ private final AtomicLong min = new AtomicLong(Long.MAX_VALUE);
+
+ /**
+ * The max value of the time spent for one call
+ */
+ private final AtomicLong max = new AtomicLong(-1);
+
+ /**
+ * The total time spent for all the calls
+ */
+ private final AtomicLong total = new AtomicLong();
+
+ /**
+ * The total amount of calls
+ */
+ private final AtomicLong times = new AtomicLong();
+
+ /**
+ * The {@link ThreadLocal} used to keep the initial timestamp
+ */
+ private final ThreadLocal<Queue<Long>> currentTime = new ThreadLocal<Queue<Long>>()
+ {
+ protected Queue<Long> initialValue()
+ {
+ return new LinkedList<Long>();
+ }
+ };
+
+ /**
+ * The default constructor
+ * @param parent the global statistics on the top of the current ones
+ * @param description the description of the statistics, to be compatible with the CSV format
+ * all ',' will be replaced with ';'
+ */
+ public Statistics(Statistics parent, String description)
+ {
+ this.parent = parent;
+ this.description = description.replace(',', ';');
+ }
+
+ /**
+ * Start recording
+ */
+ public void begin()
+ {
+ if (parent != null)
+ {
+ parent.onBegin();
+ }
+ onBegin();
+ }
+
+ /**
+ * Store the current timestamp in the {@link ThreadLocal}
+ */
+ private void onBegin()
+ {
+ Queue<Long> q = currentTime.get();
+ q.add(System.currentTimeMillis());
+ }
+
+ /**
+ * Stop recording
+ */
+ public void end()
+ {
+ onEnd();
+ if (parent != null)
+ {
+ parent.onEnd();
+ }
+ }
+
+ /**
+ * Refresh the values of the metrics (min, max, total and times)
+ */
+ private void onEnd()
+ {
+ long result = System.currentTimeMillis() - currentTime.get().poll();
+ times.incrementAndGet();
+ if (result < min.get())
+ {
+ min.set(result);
+ }
+ if (max.get() < result)
+ {
+ max.set(result);
+ }
+ total.addAndGet(result);
+ }
+
+ /**
+ * Print the description of all the metrics into the given {@link PrintWriter}
+ */
+ public void printHeader(PrintWriter pw)
+ {
+ pw.print(description);
+ pw.print("-Min,");
+ pw.print(description);
+ pw.print("-Max,");
+ pw.print(description);
+ pw.print("-Total,");
+ pw.print(description);
+ pw.print("-Avg,");
+ pw.print(description);
+ pw.print("-Times");
+ }
+
+ /**
+ * Print the current snapshot of the metrics and evaluate the average value
+ */
+ public void printData(PrintWriter pw)
+ {
+ long lmin = min.get();
+ if (lmin == Long.MAX_VALUE)
+ {
+ lmin = -1;
+ }
+ long lmax = max.get();
+ long ltotal = total.get();
+ long ltimes = times.get();
+ float favg = ltimes == 0 ? 0f : (float)ltotal / ltimes;
+ pw.print(lmin);
+ pw.print(',');
+ pw.print(lmax);
+ pw.print(',');
+ pw.print(ltotal);
+ pw.print(',');
+ pw.print(favg);
+ pw.print(',');
+ pw.print(ltimes);
+ }
+
+ /**
+ * @return The min value of the time spent for one call
+ */
+ public long getMin()
+ {
+ long lmin = min.get();
+ if (lmin == Long.MAX_VALUE)
+ {
+ lmin = -1;
+ }
+ return lmin;
+ }
+
+ /**
+ * @return The max value of the time spent for one call
+ */
+ public long getMax()
+ {
+ return max.get();
+ }
+
+ /**
+ * @return The total time spent for all the calls
+ */
+ public long getTotal()
+ {
+ return total.get();
+ }
+
+ /**
+ * @return The total amount of calls
+ */
+ public long getTimes()
+ {
+ return times.get();
+ }
+
+ /**
+ * @return The average time spent for one call
+ */
+ public float getAvg()
+ {
+ long ltotal = total.get();
+ long ltimes = times.get();
+ float favg = ltimes == 0 ? 0f : (float)ltotal / ltimes;
+ return favg;
+ }
+
+ /**
+ * Reset the statistics
+ */
+ public void reset()
+ {
+ min.set(Long.MAX_VALUE);
+ max.set(0);
+ total.set(0);
+ times.set(0);
+ }
+}
\ No newline at end of file
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/statistics/TestJCRStatisticsManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/statistics/TestJCRStatisticsManager.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/statistics/TestJCRStatisticsManager.java 2010-04-13 07:03:28 UTC (rev 2268)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.statistics;
+
+import junit.framework.TestCase;
+
+/**
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 12 avr. 2010
+ */
+public class TestJCRStatisticsManager extends TestCase
+{
+
+ public void testFormatName()
+ {
+ assertNull(JCRStatisticsManager.formatName(null));
+ assertEquals("myMethod(String, String)", JCRStatisticsManager.formatName("myMethod(String, String)"));
+ assertEquals("myMethod(String, String)", JCRStatisticsManager.formatName(" myMethod (String , String) "));
+ assertEquals("myMethod(String, String)", JCRStatisticsManager.formatName("myMethod(String;String)"));
+ assertEquals("myMethod(String, String)", JCRStatisticsManager.formatName("myMethod(String,String)"));
+ }
+}
16 years