28. Wicket Metrics Monitoring (Experimental)
The wicket-metrics module is available since Wicket 7.3.0 and contains a life measurement implementation to collect data of applications and visualize it.
You can see how many request your application served, how often components are created, initalized, configured or their detach method has been invoked and a lot of other additional information.
The module itself is using Metrics of dropwizard and AspectJ so that if you turn of the measurement it has no longer any effect
to your web application.
Keep in mind that AspectJ is licensed under the Eclipse Public License and you should provide the required license information.
28.1. Example setup
This is a little example how to setup wicket-metrics within a Apache Tomcat.
(1) Add the maven dependency to your project
<dependency>
<groupId>org.apache.wicket.experimental.wicket8</groupId>
<artifactId>wicket-metrics</artifactId>
<version>0.X-SNAPSHOT</version>
</dependency>
(2) Just drop the jars of aspectjrt and aspectjweaver into the tomcat lib folder - you can download it from here http://mvnrepository.com/artifact/org.aspectj/ (the metrics dependency is shipped with the project)
(3) Add the java agent to the jvm start options of your tomcat: -javaagent:/pathToServer/lib/aspectjweaver-x.x.x.jar
(4) Add an aop.xml to your project’s META-INF folder at the root of your classpath with the metrics you want to use (aspect tags) - if you don’t want to enable a metrics just remove the aspect tag:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-nowarn">
<include within="org.apache.wicket..*"/>
</weaver>
<aspects>
<!-- required -->
<aspect name="org.apache.wicket.metrics.aspects.WicketFilterInitAspect" />
<!-- optional -->
<aspect name="org.apache.wicket.metrics.aspects.model.LoadableDetachableModelLoadAspect" />
<aspect name="org.apache.wicket.metrics.aspects.requesthandler.IRequestHandlerDetachAspect" />
<aspect name="org.apache.wicket.metrics.aspects.requesthandler.IRequestHandlerRespondAspect" />
<aspect name="org.apache.wicket.metrics.aspects.resource.IResourceCreateAspect" />
<aspect name="org.apache.wicket.metrics.aspects.behavior.BehaviorCreateAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentCreateAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentOnConfigureAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentOnDetachAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentOnInitializeAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentOnRenderAspect" />
<aspect name="org.apache.wicket.metrics.aspects.component.ComponentSetResponsePageAspect" />
<aspect name="org.apache.wicket.metrics.aspects.ajax.IPartialPageRequestHandlerAddAspect" />
<aspect name="org.apache.wicket.metrics.aspects.ajax.IPartialPageRequestHandlerAppendJavaScriptAspect" />
<aspect name="org.apache.wicket.metrics.aspects.ajax.IPartialPageRequestHandlerPrependJavaScriptAspect" />
<aspect name="org.apache.wicket.metrics.aspects.resource.ResourceReferenceCreateAspect" />
<aspect name="org.apache.wicket.metrics.aspects.markup.WicketTagCreateAspect" />
<aspect name="org.apache.wicket.metrics.aspects.request.WicketFilterRequestCycleUrlAspect" />
<aspect name="org.apache.wicket.metrics.aspects.request.WicketFilterRequestCycleAspect" />
<aspect name="org.apache.wicket.metrics.aspects.session.SessionCountListenerAspect" />
</aspects>
</aspectj>
- If you use the SessionCountListenerAspect you have to ensure that metadata-complete= [false] is set otherwise you have to add the listener yourself:
<listener>
<listener-class>
org.apache.wicket.metrics.aspects.session.SessionCountListener
</listener-class>
</listener>
(5 - optional) To enable the JMX measurement write the following line into your init method of your Application (Now you are able to connect with jvisualvm to your server and have a look at the data):
WicketMetrics.getSettings().startJmxReporter();
To deactivate:
WicketMetrics.getSettings().stopJmxReporter();
To disable measurement:
WicketMetrics.getSettings().setEnabled(false);
IMPORTANT INFORMATION It is only possible to collect metrics for one wicket filter per webapp - don’t declare more then one if you want to use wicket-metrics The WicketFilterInitAspect is required so that the application can be resolved - otherwise runtime exceptions will be thrown If you use the SessionCountListener you have to clear the session store if you restart the server - otherwise physically stored session will corrupt the data, because the count is initialized with 0. If you have set wicket-metrics as dependency you can open wicket-metrics.template.xml to get a full template of the aop.xml. For the weaver options refer to the AspectJ LTW configuration documentation: https://eclipse.org/aspectj/doc/next/devguide/ltw-configuration.html |
28.2. Visualization with Graphite
To visualize the metrics with Graphite a little additional configuration is required:
(1) Add the additional maven dependency to your project:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-graphite</artifactId>
<version>${metrics.graphite.version}</version>
</dependency>
- the metrics.graphite.version should be the same as the metrics version of the wicket-metrics dependency. Check the Maven dependencies to ensure this.
(2) Add the following code to your Application’s init method:
private GraphiteReporter reporter;
@Override
protected void init()
{
MetricRegistry metricRegistry = WicketMetrics.getMetricRegistry();
final Graphite graphite = new Graphite(new InetSocketAddress("127.0.0.1", 2003));
reporter = GraphiteReporter.forRegistry(metricRegistry).prefixedWith("WebApplications")
.convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL).build(graphite);
// Collects data every 5 seconds
reporter.start(5, TimeUnit.SECONDS);
}
@Override
protected void onDestroy()
{
super.onDestroy();
reporter.stop();
}
(3) Install and setup graphite on your system. Example installation for Mac (beware that this is only a quickstart setup!):
(1) Install homebrew: brew
(2) Install Git
(3) brew install python
(4) brew install cairo
(5) brew install py2cairo
(6) pip install Django==1.5
(7) pip install “django-tagging<0.4”
(8) sudo pip install carbon
(9) pip install whisper
(10) sudo pip install graphite-web
(11) sudo pip install Twisted==11.1.0
(12) sudo chown -R
:staff /opt/graphite (13) cp /opt/graphite/conf/carbon.conf{.example,}
(14) cp /opt/graphite/conf/storage-schemas.conf{.example,}
(15) cd /opt/graphite/webapp/graphite
(16) cp local_settings.py{.example,}
(17) python manage.py syncdb
(18) python /opt/graphite/bin/carbon-cache.py start
(19) python /opt/graphite/bin/run-graphite-devel-server.py /opt/graphite
(20) Go to http://localhost:8080
- (18) and (19) have to be executed if the mac has been restarted
(4) Now start your tomcat server configured like mentioned in the previous chapter.
28.3. Measured data
The data which is going to be measured depends on the wicket-metrics implementation. So it doesn’t make any sense to collect time data
about setResponsePage, but it does for the constructor of components, to see if a component needs a long time to be created. You can
get the information about which data has been collected from out of the mbeans.
Here are some information about them:
max - the maximal time for a task (created, initialized, etc.)
min - the minimal time for a task (created, initialized, etc.)
count - how often something happened (request count)
The structure is separated in the way that under core there are the kind of components measured and below that the type of operation
(created, initialized, detached). In this category every component is listed dynamically.
28.4. Write own measurements
There are only a two steps required to write own measurements for life data statistics in Wicket:
(1) Write a class which is named very close to what it measures. This class should extends WicketMetrics and should annotated with @Aspect and provide one method with a join point scanning for the target signature.
@Aspect
public class MySpecialAspect extends WicketMetrics
{
@Around("execution(* my.package.MyClass.myMethod(..))")
public Object aroundRequestProcessed(ProceedingJoinPoint joinPoint) throws Throwable
{
return measureTime("mycategory/someinformation/", joinPoint);
}
}
To measure time you need @Around because measureTime of WicketMetrics requires the joinPoint - the class name is appended with a slash at the end
To only mark that a method is called you can use mark of WicketMetrics and apply null as a second parameter - if you apply a join point to mark the class name is appended with a slash at the end
(2) Add the class to your aop.xml and of course the package to scan for classes that are target for your measurements:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-nowarn">
<include within="org.apache.wicket..*"/>
<include within="my.components.package..*"/>
</weaver>
<aspects>
<!-- required -->
<aspect name="org.apache.wicket.metrics.aspects.WicketFilterInitAspect" />
<!-- own aspects -->
<aspect name="my.aspect.package.MySpecialAspect" />
<!-- wickets own metrics -->
.....
</aspects>
</aspectj>