/ Management  

This is how you fix the Log4J2’s Application_Server.xml timestamps that drive you crazy

Hi there “Process Automation” fans,

Welcome to a new installment of “Process Automation” tips.

If you’re an “administrator”, “installator”, or “developerator”, you always want to get your eyes on logging. I’m not talking about the terrible ‘Log Viewer’ artifact from design-time, but I’m talking real log-files directly at the server. How? Well, by simply creating a read-only network-share on these locations:

1
2
3
4
5
6
7
#The platform logging with Application_Server.xml
/opt/opentext/ProcessAutomationCE/defaultInst/Logs/
#The TomEE application server with cataline.out, etc.
/opt/tomee/apache-tomee-plus-10.0.0/logs/
#The Tomcat application server for OTDS with otds.log, directory-provenance.log, etc.
/opt/tomcat/apache-tomcat-10.1.34/logs/
#You can add any other logs to this list like xECM and DCTM logs!?

But my manager tells me this sharing is not possible/allowed!? Interesting question, would that manager also hire a carpenter asking to leave his hammer at home? I guess not OR they have the expectation that the nail is still not in the wall after a day. 🤣 I’m joking, and I hear you; I also know how big corporates work.

However, this post is not about log-files accessibility; It’s about readability…Watch and learn!


Let’s get right into it…

Have you ever watched the Application_Server.xml on the OPA server (in $CORDYS_HOME/Logs). If so, this is a snipped:

1
2
3
4
5
<log4j:event logger="com.eibus.management.AlertSystem" timestamp="1758124439748" level="INFO" thread="cn=Application Server,cn=monitor@opa,cn=monitorsoapnode@opa,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com-OutputStream">
<log4j:message><![CDATA[[Alert ID=Cordys.ESBServer.Messages.soapProcessorStarted] The Service Container cn=Business Process Management,cn=Business Process Management,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com has been started.]]></log4j:message>
<log4j:MDC><![CDATA[host=opa processid=1521]]></log4j:MDC>
<log4j:locationInfo class="com.eibus.applicationconnector.monitor.InputStreamReader" method="run" file="InputStreamReader.java" line="123"/>
</log4j:event>

When did this entry occur? Yes, at 1758124439748?? #WTF, #WHY, #WHEN, #WHO

To convert such fancy value, you can go to our friends from EpochConverter and do a conversion like this:

log4j2_001

Nice, but doing this every time is not very friendly! Can we do the smarter (incl. the removal of those annoying CDATA things)? Yes, please…


Log4j2 changes

To make this change, we first analyze the current log-file settings:
vi /opt/opentext/ProcessAutomationCE/defaultInst/config/Log4j2Configuration.xml

See the original XML source here

What does this file do…?

Top level:

  • <Configuration status="WARN">; Log4j itself will only log internal warnings or higher if something goes wrong with this config.
  • <Properties>; defines a placeholder logsFolderLocation you can set, so you can change the log file folder without editing the whole file.

Appenders (where the logs go):

  • Console appender (console)
    • Sends log output to the screen (SYSTEM_OUT).
    • Uses ‘XMLLayout’; every log entry is written as <log4j:event ...> ... </log4j:event> in XML format.
    • Includes extra info like class, method, line number (locationInfo="true").
  • File appender (file)
    • Writes logs to a file: ${logsFolderLocation}%N.xml.
    • Rolls the file every day; new file with the date suffix (.yyyy-MM-dd).
    • Keeps up to 5 old log files (DefaultRolloverStrategy max="5").
    • Also writes logs in XML format.
  • ApplicationNameBasedAppender
    • A custom appender (Cordys specific).
    • Logs go into files separated by application name.
    • Format is XML again.
  • OSBasedEventAppender (commented out)
    • Would send logs to the OS event log, but it’s disabled.
  • CordysZeroConfJDBCAppender
    • Another custom appender; sends logs into a database table.
    • “ZeroConf” means it configures itself without needing extra setup.

Loggers (what gets logged, and where):

  • Logger for CAPMethod$CapLogger
    • Level = INFO (so info, warn, error messages are logged).
    • Uses the ApplicationNameBasedAppender.
    • additivity="false"; prevents these logs from also going to the root appenders (no duplicate logging).
  • Logger for AlertSystem
    • Level = INFO.
    • Would log to the OS event log if enabled (currently disabled).
  • Logger for ManagedComponent
    • Level = INFO.
    • No appender defined, so messages just flow up to the root logger.
  • Root logger (the fallback for everything else)
    • Level = ERROR (so only errors and fatal logs are written).
    • Sends them to:
      • The file appender (daily rolling XML file).
      • The CordysZeroConfJDBCAppender (database).

In simple talk:

  • INFO logs from certain Cordys components go to special appenders (by application name, or potentially OS logs).
  • All ERROR logs go into a daily-rolling XML file and into the database.
  • Everything is written in XML format, not plain text.
  • You’ll always keep the last 5 days of log files.
  • Console also gets XML logs (useful for developers watching the server output).

In one sentence: This config writes logs as XML to the console, to daily rolling XML files, and to a database, with special handling for some Cordys components — and it only keeps 5 old log files.

Now for the great question: What is the reason we see timestamps instead of readable date/time values? Well, that’s this part <XMLLayout locationInfo="true"/>. The ‘XMLLayout’ in Log4j2 always writes in raw epoch-millis! Read more about it here.

I also read a warning on that website URL that XMLLayout is planned to be removed in the next major release! XML Layout users are strongly advised to migrate to another layout!

So, we need to get rid of it…How? Well, you can go quick and dirty replacing all of them with this ‘PatternLayout’:
<PatternLayout pattern="%d{dd-MMM-yyyy HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

This will be output:

1
18-Sep-2025 11:40:41.012 [cn=Application Server,cn=monitor@opa,cn=monitorsoapnode@opa,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com-OutputStream] INFO  com.eibus.management.AlertSystem - [Alert ID=Cordys.ESBServer.Messages.soapProcessorStarted] The Service Container cn=Business Process Management,cn=Business Process Management,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com has been started.

See the simple ‘PatternLayout’ XML source here

Nice, BUT we can do better as we want to keep the same output structure, which takes a more advanced approach with this pattern:

1
2
3
4
5
6
7
8
9
10
11
12
<PatternLayout>
<Pattern>
<![CDATA[
<log4j:event logger="%c" timestamp="%d{dd-MMM-yyyy HH:mm:ss.SSS}{Europe/Amsterdam}" level="%p" thread="%t">
<log4j:message>%enc{%m}{XML}</log4j:message>
<log4j:MDC>%enc{host=%X{host} processid=%X{processid}}{XML}</log4j:MDC>
<log4j:locationInfo class="%C" method="%M" file="%F" line="%L"/>
<log4j:throwable>%enc{%throwable{full}}{XML}</log4j:throwable>
</log4j:event>%n
]]>
</Pattern>
</PatternLayout>

The outcome? Well, watch this (and double-check the timestamp!):

1
2
3
4
5
6
<log4j:event logger="com.eibus.management.AlertSystem" timestamp="18-Sep-2025 18:08:12.887" level="INFO" thread="cn=Application Server,cn=monitor@opa,cn=monitorsoapnode@opa,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com-OutputStream">
<log4j:message>[Alert ID=Cordys.ESBServer.Messages.soapProcessorStarted] The Service Container cn=Business Process Management,cn=Business Process Management,cn=soap nodes,o=system,cn=cordys,cn=defaultInst,o=25.1.com has been started.</log4j:message>
<log4j:MDC>host=opa processid=1521</log4j:MDC>
<log4j:locationInfo class="com.eibus.applicationconnector.monitor.InputStreamReader" method="run" file="InputStreamReader.java" line="123"/>
<log4j:throwable></log4j:throwable>
</log4j:event>

See the advanced ‘PatternLayout’ XML source here


Ohwwww yeah! That’s a readable “DONE”. A little complexer than taught, but we nailed it…I find it even better! Now you see what an impact this can have on readable log files. Give it a shot yourself; Ask your administration/installation team to implement these new insights and benefit from it for the rest of your career. That’s how we do things at “OpenText Process Automation Tips”! Cheers…

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The Process Automation guy”?