Hi,

Many times and usually in production environments it is desired to generate the “access.log” file separately for different web applications so that we can monitor how the users are accessing the application, from what all IP Addresses/Hostnames the clients are accessing the application. We also want to monitor sometimes that how much time was taken by JBoss in order to process a clients request in milliseconds or in seconds.

The most desired things the cookie, incoming header, outgoing response headers, the Session or something else in the ServletRequest. So to fulfil all these requirements JBoss provides a valve “org.apache.catalina.valves.AccessLogValve” which can be enabled at an individual application level as well with the help of jboss specific deployment descriptor “jboss-web.xml”.

The AccessLogValve creates log files in the same format as those created by standard web servers. These logs can later be analyzed by standard log analysis tools to track page hit counts, user session activity, and so on. The files produces by this Valve are rolled over nightly at midnight. More informations about this Valve can be found in the following link: http://tomcat.apache.org/tomcat-5.5-doc/config/valve.html#Access_Log_Valve
Some of the useful patterns which can be used along with this valve are following:

%a - Remote IP address
%A - Local IP address
%b - Bytes sent, excluding HTTP headers, or '-' if zero
%B - Bytes sent, excluding HTTP headers
%h - Remote host name (or IP address if resolveHosts is false)
%H - Request protocol
%l - Remote logical username from identd (always returns '-')
%m - Request method (GET, POST, etc.)
%p - Local port on which this request was received
%q - Query string (prepended with a '?' if it exists)
%r - First line of the request (method and request URI)
%s - HTTP status code of the response
%S - User session ID
%t - Date and time, in Common Log Format
%u - Remote user that was authenticated (if any), else '-'
%U - Requested URL path
%v - Local server name
%D - Time taken to process the request, in millis
%T - Time taken to process the request, in seconds
%I - current request thread name (can compare later with stacktraces)

Step1). Create a directory somewhere in your file system like “/home/userone/DemoRemoteAddrValve”

Step2). Now create a directory with name “src” inside the “/home/userone/DemoRemoteAddrValve” and then place the following kind of “web.xml” file inside the “src” folder.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

        <!-- There is nothing much to write here for this demonstration. -->

</web-app>

Step3). Now write a JBoss specific we application deployment descriptor “jboss-web.xml” file inside “/home/userone/DemoRemoteAddrValve/src” directory as following:

<jboss-web>
 <valve>
   <class-name>org.apache.catalina.valves.AccessLogValve</class-name>
     <param>
        <param-name>prefix</param-name>
        <param-value>TestAccessLogValveWebApp</param-value>
     </param>
     <param>
        <param-name>suffix</param-name>
        <param-value>.log</param-value>
     </param>
     <param>
        <param-name>pattern</param-name>
        <param-value>%h %l %u %t "%r" %s %b %{User-Agent}i %{JSESSIONID}c</param-value>
     </param>
     <param>
        <param-name>directory</param-name>
        <param-value>../standalone/log</param-value>
     </param>
     <param>
        <param-name>resolveHosts</param-name>
        <param-value>false</param-value>
     </param>
   </valve>
</jboss-web>

NOTE: There is also support to write information from the cookie, incoming header, outgoing response headers, the Session or something else in the ServletRequest. It is modeled after the apache syntax:

%{xxx}i for incoming request headers
%{xxx}o for outgoing response headers
%{xxx}c for a specific request cookie
%{xxx}r xxx is an attribute in the ServletRequest
%{xxx}s xxx is an attribute in the HttpSession

Example:

     <param>
        <param-name>pattern</param-name>
        <param-value>%h %l %u %t "%r" %s %b %{User-Agent}i %{JSESSIONID}c</param-value>
     </param>

So the above pattern will also display the JSESSIONID cookie information and the User-Agent (clients browser) informations as well.

Step4). Now we will simply write a Simle JSP “index.jsp” So that we can see as soon as user will hit 10-15 request to this application the access logging will happen. Place the following JSP file inside “/home/userone/DemoRemoteAddrValve/src”

<html>
<body bgcolor=maroon>
<center><h1> Welcome Page </h1>
<font color=white>
    <h1> Check the "/home/userone/jboss-as-7.0.1.Final/standalone/log" directory</h1>
    <h3>The access log for the application might be created with the name specified in the jboss-web.xml file. </h3>
</font>
</body>
</html>

NOTE: The access log data is not immediately written in the access log …it is buffered in order to improve the performance so hit the page atleast 10-15 times and then check the access log.

Step5). Now we will write a Simple ANT Build script “build.xml” file to build the WAR file and then to deploy the application on JBoss AS7. place the following “build.xml” file inside “/home/userone/DemoRemoteAddrValve”

<project name="SingletonStartupService" default="deploy">
<property name="jboss.home" value="/home/jsenshar/JBoss_All/jboss-as-7.0.1.Final" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />
<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="output.dir" value="build" />
<property name="src.dir" value="src" />
<property name="war.name" value="TestAccessLogValveWebApp.war" />

   <path id="jboss.classpath">
     <fileset dir="${jboss.module.dir}">
        <include name="**/*.jar"/>
     </fileset>
   </path>

        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
        </target>

        <target name="build" depends="init">
           <copy todir="${tmp.dir}/WEB-INF">
                <fileset dir="${src.dir}/">
                  <include name="web.xml"/>
                  <include name="jboss-web.xml"/>
                </fileset>
           </copy>
          <mkdir dir="${tmp.dir}/WEB-INF/lib" />
          <copy file="${src.dir}/index.jsp" tofile="${tmp.dir}/index.jsp"/>
          <copy file="${src.dir}/jbossweb-7.0.1.Final.jar" tofile="${tmp.dir}/WEB-INF/lib/jbossweb-7.0.1.Final.jar"/>
          <jar jarfile="${tmp.dir}/${war.name}" basedir="${tmp.dir}" compress="true" />
          <copy file="${tmp.dir}/${war.name}" tofile="${output.dir}/${war.name}"/>
          <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}"/>
          </delete>
        </target>

        <target name="deploy" depends="build">
            <echo message="*******************  Deploying the WAR file ${war.name} *********************" />
            <echo message="********** ${output.dir}/${war.name} to ${jboss.home}/standalone/deployments **********" />
            <copy todir="${jboss.home}/standalone/deployments/">
                <fileset dir="${output.dir}/">
                  <include name="${war.name}"/>
                </fileset>
            </copy>
            <echo message="*******************  Deployed Successfully   *********************" />
        </target>
</project>

Step6). Now open a Shell prompt and then set the PATH pointing to the ANT bin directory and the JDK bin directory … like following and the just run the “ant” command:

For Unix Based OS:
export PATH=/home/userone/jdk1.6.0_21/bin:/home/userone/org.apache.ant_1.6.5/bin:$PATH

OR

For Windows Based OS:
set PATH=C:jdk1.6.0_21bin:C:org.apache.ant_1.6.5bin:%PATH%

[userone@localhost TestEE6Feature]$ ant
Buildfile: build.xml

init:
   [delete] Deleting directory /home/userone/TestAccessLogValve/build
    [mkdir] Created dir: /home/userone/TestAccessLogValve/build
    [mkdir] Created dir: /home/userone/TestAccessLogValve/tmp

build:
     [copy] Copying 2 files to /home/userone/TestAccessLogValve/tmp/WEB-INF
    [mkdir] Created dir: /home/userone/TestAccessLogValve/tmp/WEB-INF/lib
     [copy] Copying 1 file to /home/userone/TestAccessLogValve/tmp
     [copy] Copying 1 file to /home/userone/TestAccessLogValve/tmp/WEB-INF/lib
      [jar] Building jar: /home/userone/TestAccessLogValve/tmp/TestAccessLogValveWebApp.war
     [copy] Copying 1 file to /home/userone/TestAccessLogValve/build
   [delete] Deleting 5 files from /home/userone/TestAccessLogValve/tmp
   [delete] Deleted 3 directories from /home/userone/TestAccessLogValve/tmp

deploy:
     [echo] *******************  Deploying the WAR file TestAccessLogValveWebApp.war *********************
     [echo] ********** build/TestAccessLogValveWebApp.war to /home/userone/jboss-as-7.0.1.Final/standalone/deployments **********
     [copy] Copying 1 file to /home/userone//deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL
Total time: 0 seconds

NOTE: The only change you will need to make is to change the “jboss.home” value in the above ANT build.xml file to point to your own JBoss AS& directory.

Step7). Start the JBoss AS& like following from inside your “/home/userone/jboss-as-7.0.1.Final/bin” directory.

   ./standalone.sh --server-config standalone-preview.xml

NOTE: Due to some reasons if you find that access log is not getting generated after deploying/redeploying your application then¬† Undeploy the application then clear the “data” and “tmp” directory and then freshly deploy your application. or check the path of the access log which you entered is correct or not?

<param>
<param-name>directory</param-name>
<param-value>../standalone/log</param-value>
</param>

Enabling Access Log Valve at Whole JBossAS 7.1.2 level

Similarly if you want to configure Access Log Valve at whole server level then you can add the tag inside the “web” subsystem of your server. AS 7.1.1 or AS 7.1.2

[standalone@localhost:9999 /] /subsystem=web/virtual-server=default-host/access-log=configuration:add(pattern="%h %l %u %t "%r" %s %b %{User-Agent}i %{JSESSIONID}c")
{"outcome" => "success"}


[standalone@localhost:9999 /] /subsystem=web/virtual-server=default-host/access-log=configuration/directory=configuration:add(path="TestAccessLog", relative-to="jboss.server.log.dir")
{"outcome" => "success"}


[standalone@localhost:9999 /] /subsystem=web/virtual-server=default-host/access-log=configuration/:read-resource(recursive=true,proxies=false,include-runtime=false,include-defaults=true)
{
    "outcome" => "success",
    "result" => {
        "extended" => false,
        "pattern" => "%h %l %u %t "%r" %s %b %{User-Agent}i %{JSESSIONID}c",
        "prefix" => false,
        "resolve-hosts" => false,
        "rotate" => true,
        "directory" => {"configuration" => {
            "path" => "TestAccessLog",
            "relative-to" => "jboss.server.log.dir"
        }}
    }
}

It will generate the following kind of configuration inside your “web” subsystem:

        <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
            <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
            <virtual-server name="default-host" enable-welcome-root="true">
                <alias name="localhost"/>
                <alias name="example.com"/>

                <access-log pattern="%h %l %u %t "%r" %s %b %{User-Agent}i %{JSESSIONID}c">
                    <directory path="TestAccessLog"/>
                </access-log>

            </virtual-server>
        </subsystem>

.
.
Thanks
Middleware Magic Team

0saves
If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.