To integrate MoSKito into your application and monitor your data and code with AOP, follow two simple steps.
Step 1: Annotate classes and methods
For classes, add @Monitor annotation.
For methods, add the same @Monitor annotation.
To monitor a class but exclude some of its methods:
- Add @Monitor annotation to the target class.
- Add @DontMonitor annotation to the methods you want to skip.
The same workflow applies to Counters.
You can also specify a producerId, subsystem or category to monitor:
Step 2: Alter pom.xml
After annotating the classes for monitoring, tell the compiler to actually weave them. In Maven, this is done by adding the following two blocks to your pom.xml:
and now the build section:
This is it.
The CDI integration is pretty similar to the AOP integration, but has differences. Anyway, CDI also involves two simple steps.
Step 1: Annotate classes and methods
For classes, add @Monitor annotation (in the same way with AOP).
You may bind an annotation with a special value, later used to map a specific interceptor.
For example, we provide DAO, SERVICE or WEB interceptors, which automatically put the registered producers into specific categories.
For methods, use the same @Monitor annotation.
Step 2: Add interceptors to beans.xml and to the project
To activate MoSKito interceptor (either your own or built-in) for CDI, add it to beans.xml:
The WEB Integration is divided into several subparts.
MoSKito comes with a set of built-in filters for different counting purposes. All the following filters are monitoring the same stat type, FilterStats. The difference is the extraction of the stat name itself. For example, RequestURIFilter separates calls by URL and the DomainFilter - by called server name.
Below are the filters in version 2.2.3:
Separates traffic by top level source domain. This Filter is more secure than SourceTldFilter because it:
a) performs the lookup asynchronously, without support from container, and
b) is invulnerable to DNS attacks, for the same reason as a).
|net.anotheria.moskito.web.filters.DomainFilter||Separates traffic by called server name.|
|net.anotheria.moskito.web.filters.MethodFilter||Separates traffic by HTTP Method (GET, POST, PUT).|
|net.anotheria.moskito.web.filters.RefererFilter||Separates traffic by referrer (if any).|
|net.anotheria.moskito.web.filters.RequestURIFilter||Separates traffic by URL, in other words, you get request count, time, etc., for each callable URL in your system.|
|net.anotheria.moskito.web.filters.SourceIpSegmentFilter||Separates traffic by the first byte of IP4 Address.|
|net.anotheria.moskito.web.filters.SourceTldFilter||Separates traffic by top level client domain. This filter relies on container's resolving, which is switched off by default on most containers.|
|net.anotheria.moskito.web.filters.UserAgentFilter||Separates traffic by User Agent. Unfortunately, this filter uses the whole user-agent header as stat name and not just browser. The latter would be great, we are looking for contributions|
For all the above filters the integration is done via web.xml:
The limit parameter is used to prevent memory overload.
Since the number of stats is mostly unknown to MoSKito, it adds new entries on the fly. However, since every URL, called once, will be monitored, it would be easy to attack a monitored site by simply calling non-existing URLs.
To prevent this attack, a limit on supported stat name size is applied. 1000 should be a good limit for most production sites.
All the above filters (or almost all) are built with the same principle:
- Extend net.anotheria.moskito.web.MoskitoFilter,
- Implement protected abstract String extractCaseName(ServletRequest req, ServletResponse res ).
For example, the DomainFilter:
Feel free to create your own
MoSKito comes with 2 built-in session listeners: net.anotheria.moskito.web.session.SessionByTldListener and net.anotheria.moskito.web.session.SessionCountProducer. SessionCountProducer simply counts all sessions. SessionByTldListener (which is also a producer, sorry for naming inconvenience) does the same that SessionCountProducer does, but additionally it counts by client's TLD.
So, you would be able to monitor how many of your users are coming from China, from France, from Canada and so on.
Both are integrated via web.xml:
Both are counting new sessions, current sessions, deleted sessions and min/max active sessions, from start and within an interval.
There is an easy way to integrate a servlet, by simply extending MoskitoHttpServlet and implementing doGet instead of get.
java.lang.Proxy - proxies are excellent to create monitoring proxies around implementations you want to monitor. MoSKito provides a special ProxyUtils class, that allows to create MonitoringProxies in a quick and easy way.
Let;s assume you created a service:
and an implementation:
All you need to do is to wrap your implementation with a proxy and you are done:
This method is a shortcut method that hunts a lot of implementation details from you. The three parameters are:
|The instance to be monitored.|
|Subsystem. All producers have a subsystem, a category and a producer name/id. The category is guessed from method's name - "service",|
the producer id will be generated out of the class name. Subsystem remains.
The interface that should be monitored. You can specify multiple (varargs). Only methods in the specified interfaces will be monitored. If you call toString() in the example above,
The above call creates a new monitored instance. We strongly advice you to create more than one monitoring instances of your classes, allowing you to separate traffic by source. However, creating a new monitoring instance on each call is counterproductive and will lead to a memory leak.
More ProxyUtils methods:
Note on ProxyUtils
The following pattern is used to name the created producers:
CLASSNAME + "-" + instanceCounter (starting with 1)
In the above example, the ProducerId would be SimpleService-1, not SimpleService. This pattern is a part of duplicate prevention mechanism that doesn't allow producers to be overwritten.
However, the ProxyUtils themselves are only a utility class on top of the MoskitoInvokationProxy (net.anotheria.moskito.core.dynamic.MoskitoInvokationProxy). Although you'll probably never need to use it directly, it should be named here:
|The implementation instance of the interface that we want to monitor.|
|The handler for calls on the proxy. It handles all the monitoring and accounting.|
|The IOnDemandStatsFactory for Stats.|
|Monitored interfaces (in this case one).|
Differences between AOP/CDI and Proxy style monitoring
|Monitors||... implementation.||... caller. The Caller of the method goes intercepted, the target doesn't know it's being monitored.|
|Methods||ALL. If you call an internal method in a loop and it doesn't do|
much relevant stuff, exclude it.
Only interface methods. It makes monitoring clearer, because you are usually interested in monitoring
|Limitations||-||Can only monitor interfaces.|
|Performance||Faster with compile time weaving.||A bit slower.|
|Use when...||... you want to monitor a special class or special instance, or simple don't want to build proxies.||... you have a lot of classes of a same category that pass the same code area (factories). |
This makes proxy creation very easy and effective.
GOOD OLD COUNTING
Info will be added soon.
Info will be added soon.
CallExecution is another way of telling the system when to start monitoring.
With AOP or Proxy integration, a Java method becomes a natural boundary of the start and end points of monitored period.
However, there might be situations in which only a part of a method is relevant, or even multiple critical sections in one method. This is where CallExecution comes in handy.
The first, very simple example, is where we try to monitor a part of the method. Of course, we still need a producer:
Now we have our important method, in which we want to monitor a critical section:
The main difference is that we set the monitoring boundaries manually, instead of settings them automatically with Java method boundaries.
The code below gives a clearer example of monitoring multiple areas in one method:
This is it.