Wikantik Logging Configuration Guide

This guide is for operators who need to change where Wikantik writes logs, how they rotate, or what level each component logs at. It covers the Log4j2 setup, the wikantik.use.external.logconfig switch, and the log file locations for bare-metal Tomcat and the container.

Understanding wikantik.use.external.logconfig

The Logging Stack

Wikantik routes all logging through Log4j2:

Application Code → SLF4J API → log4j-slf4j2-impl → Log4j2 Core

The relevant JARs ship in WEB-INF/lib/ of the deployed WAR; exact versions are pinned in the root pom.xml's <dependencyManagement>:

Log4j2 configuration file locations

EnvironmentConfig file path
Bare-metal local Tomcattomcat/tomcat-11/lib/log4j2.xml
Container (${CATALINA_HOME})/usr/local/tomcat/lib/log4j2.xml
Container (baked config)docker/config/log4j2-docker.xml (copied to /usr/local/tomcat/lib/log4j2.xml by the Dockerfile)

For the bare-metal install, bin/deploy-local.sh copies wikantik-war/src/main/config/tomcat/log4j2-local.xml.template to tomcat/tomcat-11/lib/log4j2.xml on first deploy (the file is preserved on subsequent deploys unless you delete it). The template uses a portable path, ${sys:catalina.base}/logs/wikantik, so it works regardless of the absolute location of the Tomcat directory.

The container build bakes docker/config/log4j2-docker.xml into the image, and docker/entrypoint.sh writes wikantik.use.external.logconfig = true into the generated wikantik-custom.properties, so the baked file is the active configuration. It writes wikantik.log and security.log to /var/wikantik/logs and sends ECS-format JSON to the console (docker logs). Container operators can volume-mount a custom log4j2.xml into /usr/local/tomcat/lib/ to override it.

How wikantik.use.external.logconfig works

When false (default): the appender.*, logger.* and rootLogger.* entries declared in ini/wikantik.properties (a console appender plus a rolling file under ${sys:java.io.tmpdir}/wikantik.log) replace whatever log4j2.xml configured. A log4j2.xml in lib/ is therefore ignored on bare-metal until you set the property to true.

  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

Because log4j2.xml is placed in tomcat/tomcat-11/lib/ (bare-metal) or /usr/local/tomcat/lib/ (container), it is on the server classloader path and Log4j2 picks it up automatically when wikantik.use.external.logconfig = true.


External XML Configuration Setup

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

Step 1: Set in wikantik-custom.properties

wikantik.use.external.logconfig = true

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

Step 2: Override the auto-generated config

bin/deploy-local.sh copies the template to tomcat/tomcat-11/lib/log4j2.xml on first deploy only. In the container the active file is /usr/local/tomcat/lib/log4j2.xml (see above).

To customize bare-metal logging, edit that file in place (it is not overwritten by subsequent bin/redeploy.sh or bin/deploy-local.sh runs). If you need to start from the template again, copy it:

# Bare-metal: restore from template
cp wikantik-war/src/main/config/tomcat/log4j2-local.xml.template \
   tomcat/tomcat-11/lib/log4j2.xml

The template uses ${sys:catalina.base}/logs/wikantik as the log directory, which resolves correctly regardless of the absolute install path. It writes wikantik.log, security.log and access.log there.

Example XML configuration

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="Wikantik-Production" monitorInterval="30">
    <Properties>
        <!-- Portable path — resolves to tomcat/tomcat-11/logs/wikantik on bare-metal -->
        <Property name="logDir">${sys:catalina.base}/logs/wikantik</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}/wikantik.log"
                     filePattern="${logDir}/wikantik-%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>
    </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>

        <!-- 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: Restart Tomcat

# Bare-metal
tomcat/tomcat-11/bin/shutdown.sh && tomcat/tomcat-11/bin/startup.sh

# Or use the fast redeploy path (also rotates catalina.out)
bin/redeploy.sh

Step 4: Verify

# Check catalina.out for startup messages (bare-metal)
tail -f tomcat/tomcat-11/logs/catalina.out

# Check new log files are created
ls -la tomcat/tomcat-11/logs/wikantik/

Path reference by environment

EnvironmentTomcat baseLog directoryConfig file
Bare-metal localtomcat/tomcat-11/tomcat/tomcat-11/logs/wikantik/tomcat/tomcat-11/lib/log4j2.xml
Container/usr/local/tomcat//var/wikantik/logs/ (set by logDir in log4j2-docker.xml)/usr/local/tomcat/lib/log4j2.xml

The bare-metal template uses ${sys:catalina.base}, which resolves to the Tomcat base directory at runtime. The container file hard-codes /var/wikantik/logs.


Customizing the log directory

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

<Properties>
    <!-- Options: -->
    <!-- Portable (recommended): -->
    <Property name="logDir">${sys:catalina.base}/logs/wikantik</Property>
    <!-- Standard Linux system log location: -->
    <!-- <Property name="logDir">/var/log/wikantik</Property> -->
    <!-- Environment variable with fallback: -->
    <!-- <Property name="logDir">${env:WIKANTIK_LOG_DIR:-/var/log/wikantik}</Property> -->
</Properties>

System property lookups

LookupDescriptionExample (bare-metal local)
${sys:catalina.base}Tomcat base directory<repo>/tomcat/tomcat-11
${sys:catalina.home}Tomcat home directory<repo>/tomcat/tomcat-11
${sys:java.io.tmpdir}Java temp directory/tmp
${sys:user.home}User home directory/home/jakefear

Important: Ensure the Tomcat process has write permission to the chosen log directory. bin/deploy-local.sh creates tomcat/tomcat-11/logs/wikantik/ automatically.


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
%X{key}Thread context map (MDC) value — used by RequestCorrelationFilter for X-Request-Id
%highlight{pattern}ANSI color highlighting

Useful Wikantik Logger Names

LoggerPurpose
com.wikantikAll Wikantik classes
com.wikantik.ui.WikiServletFilterPage 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 (value in seconds):

<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="wikantik"/>

Filter Sensitive Data

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

Sources


Cluster Hub: Wikantik Platform Development Hub: Architecture, MCP Protocols, and Agent Briefings (wikantik-development)