Wikantik Logging Configuration Guide

Understanding jspwiki.use.external.logconfig

The Logging Stack

Your Wikantik 3.0.2 uses this logging architecture:

Application Code → SLF4J API → log4j-slf4j-impl → Log4j2 Core
                              ↑
                   log4j-1.2-api (legacy bridge)

The JARs in your /opt/tomcat/webapps/ROOT/WEB-INF/lib/:

How jspwiki.use.external.logconfig Works

When Wikantik starts, WikiBootstrapServletContextListener.initWikiLoggingFramework() reads this property:

When false (default):

  1. Wikantik reads all properties from wikantik.properties / wikantik-custom.properties
  2. It filters properties starting with: appender, logger, rootLogger, filter, status, dest, name, properties, property, or log4j2
  3. These are fed into Log4j2's PropertiesConfigurationFactory
  4. Log4j2 is reconfigured programmatically

When true:

  1. Wikantik does nothing with logging configuration
  2. Log4j2 uses its standard automatic configuration mechanism
  3. It searches the classpath for: log4j2-test.xml, log4j2.xml, log4j2.properties
  4. Or you can specify -Dlog4j2.configurationFile=/path/to/config.xml

External XML Configuration Setup

Use a separate log4j2.xml file with full Log4j2 capabilities.

Step 1: Set in wikantik-custom.properties

jspwiki.use.external.logconfig = true

Also remove any existing broken logging lines (log4j.* properties are Log4j 1.x syntax and will be ignored).

Step 2: Create /opt/tomcat/lib/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="Wikantik-Production">
    <Properties>
        <Property name="logDir">/var/log/jspwiki</Property>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
    </Properties>

    <Appenders>
        <!-- Console for catalina.out -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%highlight{[%-5level]} %d{HH:mm:ss.SSS} [%t] %c{1.} - %msg%n"/>
        </Console>

        <!-- Main application log with daily rotation -->
        <RollingFile name="AppLog" fileName="${logDir}/jspwiki.log" filePattern="${logDir}/jspwiki-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="${pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="50MB"/>
            </Policies>
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>

        <!-- Security audit log -->
        <RollingFile name="SecurityLog" fileName="${logDir}/security.log" filePattern="${logDir}/security-%d{yyyy-MM-dd}.log.gz">
            <PatternLayout pattern="%d{ISO8601} %level %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
            </Policies>
            <DefaultRolloverStrategy max="90"/>
        </RollingFile>

        <!-- Access log for page views -->
        <RollingFile name="AccessLog" fileName="${logDir}/access.log" filePattern="${logDir}/access-%d{yyyy-MM-dd}.log.gz">
            <PatternLayout pattern="%d{ISO8601} %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
            </Policies>
        </RollingFile>
    </Appenders>

    <Loggers>
        <!-- Wikantik core -->
        <Logger name="com.wikantik" level="INFO" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="AppLog"/>
        </Logger>

        <!-- Security events (login, logout, access denied) -->
        <Logger name="SecurityLog" level="INFO" additivity="false">
            <AppenderRef ref="SecurityLog"/>
        </Logger>

        <!-- Page access tracking via WikiServlet -->
        <Logger name="com.wikantik.WikiServlet" level="INFO" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="AccessLog"/>
        </Logger>

        <!-- Database connection issues -->
        <Logger name="org.apache.tomcat.dbcp" level="WARN"/>

        <!-- Lucene search indexing -->
        <Logger name="com.wikantik.search" level="INFO"/>

        <!-- Root: catch-all -->
        <Root level="WARN">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Step 3: Create the log directory

sudo mkdir -p /var/log/jspwiki
sudo chown tomcat:tomcat /var/log/jspwiki

Step 4: Restart Tomcat

sudo systemctl restart tomcat

Step 5: Verify

# Check catalina.out for startup messages
tail -f /opt/tomcat/logs/catalina.out

# Check new log files are created
ls -la /var/log/jspwiki/

Customizing the Log Directory for Different Environments

The log directory is defined in the <Properties> section at the top of the XML file:

<Properties>
    <Property name="logDir">/var/log/jspwiki</Property>  <!-- Change this path -->
    <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
</Properties>

The logDir property is referenced throughout the config as ${logDir}, so changing it in one place updates all appenders:

fileName="${logDir}/jspwiki.log"
filePattern="${logDir}/jspwiki-%d{yyyy-MM-dd}-%i.log.gz"
EnvironmentPathNotes
Production/var/log/jspwikiStandard Linux log location
Development/tmp/jspwiki-logsEasy access, cleared on reboot
Testing/opt/tomcat/logs/jspwikiKeeps logs with Tomcat
Portable${sys:catalina.base}/logs/jspwikiRelative to Tomcat install
Java temp${sys:java.io.tmpdir}/jspwikiUses Java's temp directory

Using System Property Lookups

The ${sys:...} syntax references Java system properties, making configs portable across environments:

LookupDescriptionExample Value
${sys:catalina.base}Tomcat base directory/opt/tomcat
${sys:catalina.home}Tomcat home directory/opt/tomcat
${sys:java.io.tmpdir}Java temp directory/tmp
${sys:user.home}User home directory/home/tomcat

Example for development/testing:

<Properties>
    <Property name="logDir">${sys:catalina.base}/logs/jspwiki</Property>
    <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
</Properties>

Environment Variables

You can also use environment variables with the ${env:...} syntax:

<Property name="logDir">${env:JSPWIKI_LOG_DIR:-/var/log/jspwiki}</Property>

This uses $JSPWIKI_LOG_DIR if set, otherwise falls back to /var/log/jspwiki.

Important Reminders

  1. Permissions: Ensure the tomcat user has write permission to the chosen directory
  2. Create directory: The directory must exist before Tomcat starts (Log4j2 won't create parent directories)
  3. Disk space: Choose a location with adequate space for log rotation
# Example setup for testing environment
sudo mkdir -p /opt/tomcat/logs/jspwiki
sudo chown tomcat:tomcat /opt/tomcat/logs/jspwiki

Log4j2 Configuration Reference

Log Levels (in order of severity)

LevelDescription
TRACEFinest-grained debug information
DEBUGDetailed debug information
INFOGeneral operational messages
WARNWarning conditions
ERRORError conditions
FATALCritical errors causing shutdown

Common Pattern Layout Tokens

TokenDescription
%d{pattern}Date/time with specified format
%tThread name
%p or %levelLog level
%c{n}Logger name (n = precision)
%C{n}Class name
%MMethod name
%LLine number
%m or %msgLog message
%nNewline
%xThread context (NDC)
%X{key}Thread context map (MDC) value
%highlight{pattern}ANSI color highlighting

Useful Wikantik Logger Names

LoggerPurpose
com.wikantikAll Wikantik classes
com.wikantik.WikiServletPage request handling
com.wikantik.authAuthentication/authorization
com.wikantik.searchLucene search indexing
com.wikantik.providersPage/attachment providers
SecurityLogSecurity audit events
SpamLogSpam filter events

Advanced Features

Hot Reload Configuration

Add monitorInterval to automatically reload config changes:

<Configuration status="WARN" monitorInterval="30">

Async Logging (Performance)

Wrap appenders for non-blocking logging:

<Appenders>
    <RollingFile name="AppLogFile" .../>
    <Async name="AppLog">
        <AppenderRef ref="AppLogFile"/>
    </Async>
</Appenders>

Syslog Appender (Centralized Logging)

<Syslog name="Syslog"
        host="logserver.example.com"
        port="514"
        protocol="UDP"
        facility="LOCAL0"
        appName="jspwiki"/>

Filter Sensitive Data

<RollingFile name="AppLog" ...>
    <RegexFilter regex=".*password.*" onMatch="DENY" onMismatch="ACCEPT"/>
    <PatternLayout .../>
</RollingFile>

Sources