Todo
Fix internal references.
Kieker trace-analysis implements the special feature of Kieker allowing to monitor, analyze, and visualize (distributed) traces of method executions and corresponding timing information. For this purpose, it includes monitoring probes employing AspectJ, Java Servlet, Spring, and Apache CXF technology. Moreover, it allows to reconstruct and visualize architectural models of the monitored systems, e.g., as sequence and dependency diagrams.
In this tutorial, we will instrument a Java Servlet application with interceptors and AspectJ. For other options to generate traces in Java and other programming languages, please consult the respective pages in How to perform Trace Analysis and How to apply Kieker in Java EE Environments.
We use the OperationExecutionRecord
from the controlflow
package
to collect trace information. There is also an alternative
flow
-based set of monitoring events which can be used alternatively.
However, they are not used in this tutorial. More information on
monitoring traces can be found in tutorials-how-to-perform-trace-analysis.
The OperationExecutionRecord
attributes operationName
, tin
,
and tout
represent the full qualified name of the operation
including the class name, the time before execution of the operation and
the time after the execution, respectively (see JavaDoc
OperationExecutionRecord).
The attributes traceId
and sessionId
are used to store trace and
session information; eoi
and ess
contain control-flow
information needed to reconstruct traces from monitoring data. For
details please refer to the technical report and
JavaDoc.
A basic understanding of how Kieker performs monitoring (see Getting Started)
Basic knowledge of AspectJ, i.e., that it is an aspect-oriented approach and technology
Basic knowledge what a Servlet application is
Docker, in case you want to use docker to run the example (optional)
Download the Servlet Engine Jetty (tested with 9.4.30)
Checkout the JPetStore here and switch to the single-jpetstore branch, for a vanilla JPetStore. Please note: There is also a variant pre-configured with Kieker probes utilizing the flow events instead of the controlflow events used in this tutorial.
git clone https://github.com/research-iobserve/jpetstore-6.git
cd jpetstore-6
git checkout single-jpetstore
Now it is time to check whether your version compiles with
mvn compile package
This produces an output similar to
[INFO]
[INFO] --- maven-war-plugin:3.1.0:war (default-war) @ jpetstore ---
[INFO] Packaging webapp
[INFO] Assembling webapp [jpetstore] in [/home/user/jpetstore-6/target/jpetstore]
[INFO] Processing war project
[INFO] Copying webapp resources [/home/user/jpetstore-6/src/main/webapp]
[INFO] Webapp assembled in [97 msecs]
[INFO] Building war: /home/user/jpetstore-6/target/jpetstore.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.034 s
[INFO] Finished at: 2020-06-15T13:22:23+02:00
[INFO] ------------------------------------------------------------------------
The resulting war file is located in target
inside the main project
directory jpetstore-6
and named jpetstore.war
.
JPetStore is a small demonstration example of a Servlet based application. That means external HTTP requests to the application trigger a trace through the application. Therefore, we must instrument the incoming request and all subsequent method calls through the application. Thus, we must use Servlet interceptors and instrument all methods, which we can do with AspectJ.
The Java Servlet API includes the javax.servlet.Filter
interface.
It can be used to implement interceptors for incoming HTTP requests.
Kieker provides a SessionAndTraceRegistrationFilter
probe which
implements the javax.servlet.Filter
interface. It initializes the
session and trace information for incoming requests. If desired, it
additionally creates an OperationExecutionRecord
for each
invocation of the filter and passes it to the MonitoringController
.
To integrate the interceptor into the application, you must add a filter
configuration to the web.xml
file. The web.xml file is located in
jpetstore-6/src/main/webapp/WEB-INF
<filter>
<filter−name>sessionAndTraceRegistrationFilter</filter−name>
<filter−class>kieker.monitoring.probe.servlet.SessionAndTraceRegistrationFilter</filter−class>
<init−param>
<param−name>logFilterExecution</param−name>
<param−value>true</param−value>
</init−param>
</filter>
<filter−mapping>
<filter−name>sessionAndTraceRegistrationFilter</filter−name>
<url−pattern>/∗</url−pattern>
</filter−mapping>
In the above snippet, the Kieker class
kieker.monitoring.probe.servlet.SessionAndTraceRegistrationFilter
implementing the probe is registered in the Servlet application and the
filter-mapping
assigns it to all Servlet URLs.
While the Servlet filter above will collect all HTTP requests to the application, it cannot collect the traces within the application. Therefore, we have to apply probes to all methods. In this tutorial, we use AspectJ and Kieker’s AspectJ probes to accomplish this goal.
Kieker includes the AspectJ-based monitoring
probes OperationExecutionAspectAnnotation
, OperationExecu-tionAspectAnnotationServlet
, OperationExecutionAspectFull
,
and OperationExecutionAspectFullServlet
which can be woven into
Java applications at compile time and load time. These probes monitor
method executions and corresponding trace and timing information. The
probes with the postfix Servlet
additionally store a session
identifier within the OperationExecutionRecord
. For this tutorial,
we use OperationExecutionAspectFull
probe to collect trace
information.
To configure AspectJ, we have to create an aop.xml
file and place it
src/main/resources
within the jpetstore-6 project directory. It
contains the following lines:
<!DOCTYPE aspectj PUBLIC "−//AspectJ//DTD//EN" "http://www.aspectj.org/dtd/aspectj_1_5_0.dtd">
<aspectj>
<weaver options="">
<include within="org.mybatis..*"/>
</weaver>
<aspects>
<aspect name="kieker.monitoring.probe.aspectj.operationExecution.OperationExecutionAspectFull"/>
</aspects>
</aspectj>
Line 5 specifies which classes and methods within the project shall be
instrumented. The org.mybatis..*
limits the instrumentation to
classes of the project itself and ignores all imported jar files, as we
are not interested to clutter the results with API internals. Line 9
selects the aspect OperationExecutionAspectFull
. As indicated by
its name, this aspect makes sure that every method within the included
classes/packages will be instrumented and monitored.
The JPetStore example uses Maven to build the application. Therefore, we
have now to adapt the build configuration to use AspectJ and Kieker.
Maven is configured by a pom.xml
file located in the project root
directory.
Open the pom.xml
in an editor. Here you must add
the dependencies for Kieker and AspectJ, and
the AspectJ compile time weaving.
In the dependency section of the pom.xml
add:
<dependency>
<groupId>net.kieker-monitoring</groupId>
<artifactId>kieker</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.7</version>
</dependency>
In the build section of the pom.xml
add:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<complianceLevel>1.7</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>net.kieker-monitoring</groupId>
<artifactId>kieker</artifactId>
</aspectLibrary>
</aspectLibraries>
<xmlConfigured>${basedir}/src/main/resources/aop.xml</xmlConfigured>
<sources>
<source>
<basedir>${basedir}/src/main/java</basedir>
<includes>
<include>**/**.java</include>
</includes>
</source>
</sources>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Please note that the src/main/resources/aop.xml
is explicitly
specified in the configuration.
The last step is to place a Kieker configuration file within the
application to instruct the MonitoringController where and how to
store the monitoring data. The kieker.monitoring.properties
file
should contain the following information and must be placed in
src/main/resources/META-INF/
within the project directory.
## The name of the Kieker instance.
kieker.monitoring.name=KIEKER
## Whether a debug mode is activated.
kieker.monitoring.debug=false
## Enable monitoring after startup
kieker.monitoring.enabled=true
## The name of the VM running Kieker or empty (will automatically be
resolved)
kieker.monitoring.hostname=
## Automatically add a metadata record
kieker.monitoring.metadata=true
## Enables the automatic assignment
kieker.monitoring.setLoggingTimestamp=true
## Register shutdown hook
kieker.monitoring.useShutdownHook=true
## Do not use JMX
kieker.monitoring.jmx=false
## The size of the thread pool used to execute registered periodic sensor jobs.
kieker.monitoring.periodicSensorsExecutorPoolSize=0
## Disable adaptive monitoring.
kieker.monitoring.adaptiveMonitoring.enabled=false
## Timer to use
kieker.monitoring.timer=kieker.monitoring.timer.SystemNanoTimer
## Report timestamps in
## Accepted values:
## 0 - nanoseconds
## 1 - microseconds
## 2 - milliseconds
## 3 - seconds
kieker.monitoring.timer.SystemMilliTimer.unit=0
## Writer configuration
kieker.monitoring.writer=kieker.monitoring.writer.filesystem.FileWriter
## output path
kieker.monitoring.writer.filesystem.FileWriter.customStoragePath=$LOGGING_DIR/
kieker.monitoring.writer.filesystem.FileWriter.charsetName=UTF-8
## Number of entries per file
kieker.monitoring.writer.filesystem.FileWriter.maxEntriesInFile=25000
## Limit of the log file size; -1 no limit
kieker.monitoring.writer.filesystem.FileWriter.maxLogSize=-1
## Limit number of log files; -1 no limit
kieker.monitoring.writer.filesystem.FileWriter.maxLogFiles=-1
## Map files are written as text files
kieker.monitoring.writer.filesystem.FileWriter.mapFileHandler=kieker.monitoring.writer.filesystem.TextMapFileHandler
## Flush map file after each record
kieker.monitoring.writer.filesystem.TextMapFileHandler.flush=true
## Do not compress the map file
kieker.monitoring.writer.filesystem.TextMapFileHandler.compression=kieker.monitoring.writer.compression.NoneCompressionFilter
## Log file pool handler
kieker.monitoring.writer.filesystem.FileWriter.logFilePoolHandler=kieker.monitoring.writer.filesystem.RotatingLogFilePoolHandler
## Text log for record data
kieker.monitoring.writer.filesystem.FileWriter.logStreamHandler=kieker.monitoring.writer.filesystem.TextLogStreamHandler
## Do not compress the log file
kieker.monitoring.writer.filesystem.TextLogStreamHandler.compression=kieker.monitoring.writer.compression.NoneCompressionFilter
## Flush log data after every record
kieker.monitoring.writer.filesystem.FileWriter.flush=true
## buffer size. The log buffer size must be big enough to hold the biggest record
kieker.monitoring.writer.filesystem.FileWriter.bufferSize=81920
Key for the writer configuration are two properties
kieker.monitoring.writer
which selects the writer and
kieker.monitoring.writer.filesystem.FileWriter.customStoragePath
which specifies where the data shall be stored. In this tutorial, we use
the kieker.monitoring.writer.filesystem.FileWriter
which can write
text and binary log files and even compress the output if necessary. If
no customStoragePath
is specified, Kieker will write to /tmp
on
Unix machines or to the respective system wide directory for temporary
files. In the above code snippet, we specified $LOGGING_DIR as location
for log files. Please choose an appropriate path within your system.
To build the example got to the project root directory and type:
mvn clean compile package
This will produce a jpetstore.war
file located in the target
directory of the jpetstore-6 project.
To run the JPetStore:
Download Jetty in case you have not done this already.
Unpack Jetty next to the jpetstore-6
project directory, e.g.,
drwxr-xr-x 11 user example 4096 Jun 15 14:32 jetty-distribution-9.4.30.v20200611
drwxrwxr-x 7 user example 4096 Jun 15 13:22 jpetstore-6
Copy the jpetstore.war
to the jetty webapps
directory
cp jpetstore-6/target/jpetstore.war jetty-distribution-9.4.30.v20200611/webapps
Switch to the Jetty directory and start the application
cd jetty-distribution-9.4.30.v20200611
java -jar start.jar
Now you can access the JPetStore from your browser with http://localhost:8080/jpetstore
While you are using the application logging information appears in a newly created Kieker logging directory, e.g.,
kieker-20200615-130444-341575577055999-UTC--KIEKER
/
kieker-20200615-130444372-UTC-001.dat
kieker.map
Feel free to explore the whole JPetStore. While browsing through the shop, you will notice that the log files will grow over time.
Monitoring data including trace information can be analyzed and visualized with the Kieker trace-analysis tool which is included in the Kieker binary distribution as well. A the tool outputs dot and pict files, tools to view such files are required. We usually use GraphViz and GnuPlot utils.
In order to use this tool, it is necessary to install two third-party pro-grams:
GraphViz A graph visualization software which can be down-loaded
from http://www.graphviz.org
GNU PlotUtils A set of tools for generating 2D plotgraphics which
can be downloaded
from http://www.gnu.org/software/plotutils/
(for Linux) and
from http://gnuwin32.sourceforge.net/packages/plotutils.htm
(for Windows).
ps2pdf Theps2pdf
tool is used to convert ps files to pdf
files.
Under Windows it is recommended to add the bin/
directories of
both tools to the “path” environment variable. It is also possible that
the GNU PlotUtils are unable to process sequence diagrams. In this case
it is recommended to use the Cygwin port of PlotUtils.
Once both programs have been installed, the Kieker
trace-analysis
tool can be used. It can be found in the tools
directory of the Kieker binary release. Unpack the
trace-analysis-1.14.zip
alongside the jpetstore-6
directory.
Start scripts can then be found in
trace-analysis-1.14/bin/trace-analysis
(Unix) and
trace-analysis-1.14/bin/trace-analysis.bat
(Windows).
Non-parameterized calls of the scripts print all possible options on the
screen.The commands shown in Listings below generate a sequence diagram
as well as a call tree to an existing directory named out/
. The
monitoring data is assumed to be located in the logging directory, e.g.,
kieker-20200615-130444-341575577055999-UTC--KIEKER/
alongside the
jpetstore-6
directory.
Before executing the trace-analysis, you need to create the out/
directory alongside the jpetstore-6
directory.
Unix version
trace-analysis-1.14/bin/trace-analysis -inputdirs kieker-20200615-130444-341575577055999-UTC--KIEKER \
-outputdirout/ \
-plot-Deployment-Sequence-Diagrams–plot-Call-Trees–short-labels
Windows version
trace-analysis-1.14/bin/trace-analysis.bat -inputdirs kieker-20200615-130444-341575577055999-UTC--KIEKER
-outputdir out\
-plot-Deployment-Sequence-Diagrams–plot-Call-Trees–short-labels
The resulting contents of the out/
directory should be similar to
the following tree:
out
/
deploymentSequenceDiagram-6120391893596504065.pic
callTree-6120391893596504065.dot
system-entities.html
The .pic
and .dot
files can be converted into other formats,
such as .pdf
, by using the GraphViz and Plot Utils
tools dot
and pic2plot
. Type the following to generate PDF
file from the graphics.
dot callTree−6120391893596504065.dot -T pdf -o callTree.pdf
pic2plot deploymentSequenceDiagram−6120391893596504065.pic-T pdf > sequenceDiagram.pdf
The scripts dotPic-fileConverter.sh
and dotPic-fileConverter.bat
convert
all .pic
and .dot
in a specified directory. The scripts can
be found in the bin directory of the Kieker binary distribution.