Accessing Log4j2 logs within an external .jar - java

I'm using Java Reflection to run code that's inside a .jar file. However, I should not modify any contents of the file, I have to use the .jar as is. Debugging is tricky (because everything is also obfuscated inside it), so I thought it might be a good idea to have a look at the logger.
I could not find any documentation that is directly relevant for this case, and to be honest I'm a little confused whether or not it is possible.
Here's the log4j2.xml that is within the .jar's root:
<Configuration status="WARN" packages="net.minecraft,com.mojang">
<Appenders>
<Console name="SysOut" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
</Console>
<Queue name="ServerGuiConsole">
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
</Queue>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
</filters>
<AppenderRef ref="SysOut"/>
<AppenderRef ref="File"/>
<AppenderRef ref="ServerGuiConsole"/>
</Root>
</Loggers>
</Configuration>
I looked around, but there does not seem to be a latest.log file, there is also no console output there.
So my question is if getting the log's output is at all possible in any way without altering this xml?
Thank you in advance,
CX

Related

log4j2 logging to console only

I have a maven web project which requires logging.
I decided to use log4j2 for that purpose and added the required entries in the pom.xml file
Then I created the log4j2.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<RollingFile name="RollingFile" fileName="${logs.path}/text.log"
filePattern="${logs.path}/%d{YYYYMMdd}-text.%i.log">
<PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" />
<Policies>
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} %-5p %c{1}:%L - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="root" level="info" additivity="false">
<appender-ref ref="RollingFile" level="info" />
<appender-ref ref="Console" level="info" />
</Logger>
<Root level="info" additivity="false">
<AppenderRef ref="RollingFile" />
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
I'm starting tomcat with -Dlogs.path="C:\mylogs", where C:\mylogs exists and has public read/write access.
The console logger is working fine, I can see the correct output in my console, the issue is that the file isn't being created, so I have no logfile, everything gets logged to catalina.out only, and the tomcat startup logs don't show errors for log4j.
What am I missing? is there some additional configuration I need to do in order to log to file?
I went through the documentation. You must refer to system properties with sys:, and it seems that tomcat properties are seen as system properties, so I replaced ${logs.path} with ${sys:logs.path} and it worked.
To create a log file with the log4j2 config you first need to define your appender. Here's an example:
<RollingFile name="MGMT"
fileName="${logdir}/mgmt.log"
filePattern="${logdir}/mgmt.%d{yyyy-MM-dd}.log">
<PatternLayout pattern="${layout}"/>
<CronTriggeringPolicy schedule="0 0 0 * * ?"/>
<DefaultRolloverStrategy>
<Delete basePath="${logdir}" maxDepth="1">
<IfFileName glob="mgmt.*.log" />
<IfAccumulatedFileCount exceeds="10" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
Afterwards you just need to define a logger that will use it:
<Logger name="the package or name that is displayed in the log line"
level="ALL"
additivity="false">
<AppenderRef ref="MGMT"/>
</Logger>
If you have a log that has com.company.test as package set that package as name for the logger. It's important that they match.
The field additivity will define if you want to pass the catched log to its parent ( true ) or just let this logger handle it ( false )
EDIT:
your config file might need this:
<Configuration status="info">
<Properties>
<Property name="logdir">${sys:catalina.base}/logs</Property>
<Property name="layout">%d [%t] %-5p %c- %m%n</Property>
</Properties>
<Appenders>
If you don't want to use this you have to define the path static like <RollingFile name="MGMT"
fileName="C:\path\file.log"

Externalize property configuration for log4j.xml

Background: I have log4j.xml file configured for our spring based application, which looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="FATAL" shutdownHook="disable" packages="com.gemstone.gemfire.internal.logging.log4j">
<Properties>
<Property name="gemfire-pattern">[%level{lowerCase=true} %date{yyyy/MM/dd HH:mm:ss.SSS z} <%thread> tid=%tid %C{1.}] %message%n%throwable%n< /Property>
</Properties>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="${gemfire-pattern}"/>
</Console>
<RollingFile name="eventLogFile" fileName="/opt/data/service/logs/events.log"
filePattern="/opt/data/service/logs/events-%d{yyyy-MM-dd}-%i.log">
<PatternLayout>
<pattern>%d{dd/MMM/yyyy HH:mm:ss,SSS} %p - %c{1}: %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="20" fileIndex="max"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.gemstone" level="INFO" additivity="true">
<filters>
<MarkerFilter marker="GEMFIRE_VERBOSE" onMatch="DENY" onMismatch="NEUTRAL"/>
</filters>
</Logger>
<Logger name="com.app.mypackage" level="INFO" additivity="true">
<AppenderRef ref="eventLogFile"/>
</Logger>
<Root level="INFO">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Now, I want log4j to write log statements with let's say 'countryName'. And, this 'countryName' should be configured via external property file.
For e.g, the "gemfire-pattern" will have this externalised property name $${countryName}.
<Property name="gemfire-pattern">[$${countryName} %level{lowerCase=true} %date{yyyy/MM/dd HH:mm:ss.SSS z} <%thread> tid=%tid %C{1.}] %message%n%throwable%n< /Property>
Considering this log4j system properties, in my case, the log4j.component.properties is not being picked up by log4j.
Any thoughts on how to fetch a property value from external properties file in log4j.xml?
References:
how-to-read-property-variable-from-file-into-log4j2
log4j system properties
log4j properties substitution
Thanks in advance.
log4j.component.properties is used to add log4j specific system properties like log4j.configurationFile, org.apache.logging.log4j.level etc.
To refer to user defined properties, include the property file inside the logback configuration and refer to the keys using ${KEY}
<configuration>
<property file="country.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${countryName}</file>
...
Logback also allows you to externalise parts of the configuration using File inclusion feature.
https://logback.qos.ch/manual/configuration.html#fileInclusion
<configuration>
<include file="src/main/java/chapters/configuration/includedConfig.xml"/>
...
Make sure the content in the external xml file is encolsed with <included> </included> tag
Note- System properties(-Dcountry="") and Environment variables can also be referred using ${PROPERTY_NAME} inside the logback configuration.

Archiving log file using log4j2 2.5

I have been trying to archive my application logs file which are older than a certain period. Noticed that since log4j 2.5 we have a Deletetag which let's you define the criteria based on which we can delete/archive our logs. Tried using this but I am somehow not able to crack it. Tried with a 30day 30d value and that isn't working on my server and neither is a 20 second policy PT20S working in my Dev Machine.
Any direction is greatly appreciated.
XML is as below:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<RollingFile name="RollingFile" fileName="C://logs///test.log" filePattern="C://logs//test-%d{MM-dd-yyyy}.log.gz" ignoreExceptions="false">
<PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<TimeBasedTriggeringPolicy />
<DefaultRolloverStrategy>
<Delete basePath="C://logs//" maxDepth="2">
<IfFileName glob="*/test-*.log.gz" />
<IfLastModified age="PT20S" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingFile" />
</Root>
</Loggers>
</Configuration>
If you're using Windows the file and filePattern of the RollingFile appender can use single slashes. The double slashes may confuse it.
You can debug by setting <Configuration status="trace"> in the beginning of the configuration file.
Update:
The rolled over files end up in the c:/logs directory (filePattern="C://logs//test-%d{MM-dd-yyyy}.log.gz").
However, the Delete action is configured to only look at files ending in "log.gz" that are in subdirectories of c:/logs. Files in the c:/logs directory itself are not matched by glob="*/test-*.log.gz".
To fix this, use glob="test-*.log.gz".
It was mentioned in the comments that changing glob to regex also resolved the problem.

log4j 2: log file being created, but not being written to

I am using log4j 2. I am trying to determine why my log file is not being written to, but my console is. This is the output I have to the console:
2016-04-25 12:26:07,142 INFO [main] helperCode.LogPlus (LogPlus.java:50) -
----------------------------------------------------------------------------
------------ The test is starting now at 2016-04-25-12-26-07-135 -----------
----------------------------------------------------------------------------
2016-04-25 12:26:07,151 INFO [main] helperCode.LogPlus (LogPlus.java:50) -
--------------------------------------------------------------------------
------------ METHOD loginBadPasswordGoodUsername_3 starting: ------------
--------------------------------------------------------------------------
The issues I've considered already:
The output is not repeating itself, so the log output being redirected is not an issue.
I am NOT using java.util.logging.Logger anywhere in my project;
The output of the log file is formatted in log4j style rather than JUL style, so I know that JUL is not overriding it;
Here is my XML config file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="FileLogger" fileName="${sys:logFilePath}" append="false">
<PatternLayout pattern="%d %t %-5p %c{2} - %m%n" />
</File>
<Async name="Async">
<AppenderRef ref="FileLogger" />
</Async>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="automationFramework" level="trace">
<AppenderRef ref="FileLogger" />
</Logger>
<Root level="trace">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
I am directing the output to the file located at the system variable "logFilePath".
I am not sure what is going on, and the config files shown on answers for similar questions are not in XML format, so I am not sure how to commute the config file code to XML.
In your case as mentioned in the comment you do not have the package called applicatiionFramework. So change the name attribute by the package name of the classes where you want to record log events.
<Logger name="your package" level="trace">
<AppenderRef ref="FileLogger" />
<Root level="trace">
<AppenderRef ref="STDOUT" />
</Root>
</Logger>
For more information visit log4j-manual-configuration
Glad the other answer helped. Do you need the named logger though? Why not just have the root logger? Also, you declared an Async Appender but are not using it. Is that on purpose? This is what I would suggest:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="FileLogger" fileName="${sys:logFilePath}" append="false">
<PatternLayout pattern="%d %t %-5p %c{2} - %m%n" />
</File>
<Async name="Async">
<AppenderRef ref="FileLogger" />
</Async>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="STDOUT" level="info" />
<AppenderRef ref="Async" />
</Root>
</Loggers>
</Configuration>
Note that you can also specify a level on the AppenderRef. I made the Console Appender level INFO to illustrate this point.
If you want the log to show location information and use Async loggers or appenders then you need to specify includeLocation="true" on the Async Appender.
For the complete noob, like myself, this line in Unknown's answer above:
<Logger name="your package" level="trace">
is the key. When it says "your package" it really means the "package foo.bar" you declared at the top of the .java file where you created the Logger, not the class name you passed to create the Logger, like:
LOGGER = LogManager.getLogger(MyClass.class.getName());
It took me a ridiculous amount of time today to get my log4j2 output going to a file, playing with various "name" values until the light bulb went on.

log4j2 configuration XML file for 2 log files with new folder each run

I am a little new to log4j2. I am looking for how I can configure the log4j2.xml file for our test automation framework. What we desire is two log files. One being non-technical and one with all the technical details, like stack trace information. This means direct INFO and ERROR messages to one file. All messages will direct to the other file. So, the one file will contain everything the other one does and more.
The other thing we desire, is everytime we run the tests it will create a new set of logs inside a folder with a time stamp.
For example
Directory Structure
Application Name
2015-12-02 16:52:30
logTechnical.log (ALL logs)
logSimple.log (INFO and ERROR)
2015-12-02 16:52:30
logTechnical.log (ALL logs)
logSimple.log (INFO and ERROR)
The other thing if possible in log4j. I think a batch file or custom code may be needed. But if we can have it keep only the 5 latest logs, so the server doesn't get messy. We don't want to use a rolling log file for this. Thanks for the help.
The following configuration creates the directory and files, but does not delete the old directories:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="Simple"
fileName="app/${date:yyyy-MM-dd HHmmss}/logSimple.log">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
<Filters>
<ThresholdFilter level="fatal" onMatch="DENY" onMismatch="NEUTRAL" />
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="NEUTRAL" />
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL" />
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
<File name="Technical"
fileName="app/${date:yyyy-MM-dd HHmmss}/logTechnical.log">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
</File>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="Simple" />
<AppenderRef ref="Technical" />
</Root>
</Loggers>
</Configuration>

Categories