Adding $USER to Log4J's log file name - java

I have a standalone Java application myApp.jar running on Linux/bash and its Log4J.xml is configured like the following:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
...
<appender name="DEFAULT_APPENDER" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/apps/my-app/logs/server.log"/>
<param name="MaxFileSize" value="10MB"/>
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss,SSS} [%t] %c %x %-5p %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="TRACE" />
<param name="LevelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
It is currently working fine with log files produced as server.log, server.log.1, server.log.2, etc...
However, I have recently found out that, other than me running the application manually with java -jar myApp.jar, the application is also run by cron job (by root). When I try to run myApp.jar manually on terminal using my account, say user123 at the same time when the crob job is running it, my command fails because I lose over file permission when generating the log files. The cron job is generating the log files with owner root and permission 664.
I am wondering if it is possible to change log4j.xml alone so that myApp.jar will produce log files with file names in such fashion: server-{$USER}.log, server-{$USER}.log.1, server-{$USER}.log.2, etc... So for example, the cron job will produce its log files like server-root.log and I, using account user123, will produce my log files in the same directory like server-user123.log
Note: I myself don't have access to root on the server.
Note: I am using Log4J version 1.x

Related

How to set size and amount of log files (stdout, stderr) in tomcat?

I recently deployed a java app on my production server. In which I have installed Tomcat version 8.5 and I have been having problems since the log files stderr and stdout grow in size exaggeratedly and therefore I lower the performance of the server or sometimes it is necessary to restart it since it does not respond. I would like to know how to configure these files so that they create only a certain amount with a specific size. I have tried configuring it through log4j it has given me error when integrating this same a tomcat. I have also configured certain parameters (for example: java.util.logging.FileHandler.limit = 1024) for logging in which the size and quantity are assigned but these do not apply to the configuration and therefore I continue to throw the server .
In a production environment, a good practice is to use a process that works with small log files, and that creates a new one if the critical size has gone.
With log4j you can use a RollingFileAppender. See the minimal configuration :
<appender name="rolling.file.appender" class="org.apache.log4j.RollingFileAppender">
<param name="maxFileSize" value="50MB" />
<param name="maxBackupIndex" value="10" />
<param name="file" value="${catalina.base}/logs/myApplication.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- Root Logger -->
<root>
<priority value="INFO" />
<appender-ref ref="rolling.file.appender" />
</root>
Documentation: https://tomcat.apache.org/tomcat-8.0-doc/logging.html

Use system properties OR variables in log4j

I want to to do like this:
<appender name="ErrorLog" class="org.apache.log4j.FileAppender">
<param name="File" value="${error.log.path}"/>
<param name="Append" value="true" />
<param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%C{1} %L [%t] %d{dd MMM,yyyy HH:mm:ss.SSS} %-5p - %m%n" />
</layout>
</appender>
Notice this line: <param name="File" value="${error.log.path}"/>
I tried to set the values like this:
public static void main(String[] args) {
System.setProperty("error.log.path", "/test/crm/log/error.log");
ApplicationContext context = new ClassPathXmlApplicationContext("blah.xml");
..........
..........
}
But I don't see any effect.
Is log4j gets configured before calling the main method?
Is there any other way to do this?
Look at this thread
It looks like you did everything right. I don't think there is any difference between setting the property inside your main class with System.setProperty() and specifying it via the command line as long as it happens befor actual log4j initialization.
I think your issue is that your logging framework gets loaded before you specify the property.
I can say that the logging framework (log4j) will get configured when you call the configurator. Stuff like BasicConfigurator.configure() (in your case its xml configurator).
Otherwise the first attempt to use the logging will cause message like "log4j is not configured properly".
The real question is whether your code snippet with 'main' is not oversimplified.
With this in mind, another question that I have to ask - whether you're running inside some container or you're running a real vanilla method main and configure everything by yourself? I'm asking because if you're running in container, the chances are that container will by itself somehow configure its logging, for example JBoss will do so. In this case more investigation is required.
Hope this helps
You can do it by configure appender pragmatically
FileAppender fa = new FileAppender();
fa.setFile("/test/crm/log/error.log");
fa.setLayout(new
PatternLayout("%C{1} %L [%t] %d{dd MMM,yyyy HH:mm:ss.SSS} %-5p - %m%n"));
fa.setThreshold(Level.ERROR);
fa.setAppend(true);
fa.activateOptions();
Logger.getRootLogger().addAppender(fa);
// similarly you can add all appenders.
// or just append file name alone
Logger log = Logger.getLogger(YourClass.class);
FileAppender appender = (FileAppender) log.getAppender("ErrorLog");
appender.setFile("appender");
System Properties can be used as ${user.home}, pick required from here http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
example :
<appender name="errorLog" class="com.qait.logger.IOPFileAppender">
<param name="Threshold" value="ERROR" />
<param name="File"
value="${user.home}/Harvestors/IOP Error Logs/error.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d%-5p [%c{1}] %m %n" />
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="ERROR" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>
Access to your property via "sys:" prefix.
Example:
<param name="File" value="${sys:error.log.path}"/>
For more information follow this link: https://logging.apache.org/log4j/2.x/manual/lookups.html
maven document:
System properties. The formats are ${sys:some.property} and ${sys:some.property:-default_value}.
from Maven Property Substitution
Setting the system property does not come into affect here. You'll need to pass it as a argument to java while executing. Try
java -Derror_log_path=/test/crm/log/error.log
Note: I am not sure if dot . works in there so replaced it with underscore _.

Rolling logs by both size and time

I use RollingFileAppender of log4j 1.2.16, which rolls log files, when they reach a certain size. Now I would like to roll log files daily and when they reach a certain size. Thus there will be one or more log files per day.
For example,
myapp.log
myapp-17.12.2013.log
myapp-16.12.2012.log
myapp-16.12.2012.1.log
myapp-16.12.2012.2.log
Is there an off-the-shelf appender, which does it already?
There are indeed two options:
use LogBack with its size and time triggering policy: http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP
there is TimeAndSizeRollingAppender for Log4J from here: http://www.simonsite.org.uk/
Keep in mind that both options use file renames. Consider this carefully if there's another script automatically moving these files. File rename is risky when two processes deal with the same file.
My suggestion is to directly write to immutable log file name in the pattern: myapp-{dd.MM.yyyy}.{X}.log. That way "rolling" is simply closing one file and opening a new one. No renames. No background threads.
The quick answer is "no". Looking at log4j's javadoc: https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/FileAppender.html
There are only two out-of-the-box file appenders: DailyRollingFileAppender and RollingFileAppender (and the first one is not recommended because it has synchronization issues).
To achieve what you want, you should create your own appender, extending RollingFileAppender and modifying it to roll the file if the day changes. The modification would be in method:
protected void subAppend(LoggingEvent event)
You can see its source here: http://www.docjar.com/html/api/org/apache/log4j/RollingFileAppender.java.html (line 274).
You just need to copy and paste the code and change the if calling rollOver to suit your needs.
Below configuration xml will do the job:
JAR required: log4j-rolling-appender-20150607-2059
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true"
xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="file"
class="uk.org.simonsite.log4j.appender.TimeAndSizeRollingAppender">
<param name="File" value="D:\\App.log" />
<param name="Threshold" value="DEBUG" />
<param name="DatePattern" value=".yyyy-MM-dd" />
<param name="MaxFileSize" value="1KB" />
<param name="MaxRollFileCount" value="100" />
<param name="ScavengeInterval" value="30000" />
<param name="BufferedIO" value="false" />
<param name="CompressionAlgorithm" value="GZ" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %-23d{ISO8601} [%t] %x: %c{1} - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="file" />
</root>
</log4j:configuration>

JASIG CAS: How do I change where log files are written to?

I know very little about Java, let alone JASIG CAS.
We are trying to implement CAS on our CentOS 6 server. We are getting the following errors:
java.io.FileNotFoundException: cas.log (Permission denied)
[...snip...]
java.io.FileNotFoundException: perfStats.log (Permission denied)
After some investigation, it seems like tomcat6 is trying to write the log files in its home directory (/usr/share/tomcat6/). I was able to determine this by chown tomcat: /usr/share/tomcat6 and then, after a restart, the log files were created in that directory.
All the other logs though are written to /usr/share/tomcat6/logs which is a symlink to /var/log/tomcat6.
I want to know how do I reconfigure CAS to write these 2 log files to a different directory /usr/share/tomcat6/logs)?
Assuming you have a recent version of CAS, it uses log4j for logging, and you can find the log4j configuration in
$CATALINA_BASE/webapps/cas-server-webapp-VERSION/WEB-INF/classes/log4j.xml
For a standard Tomcat install under CentOS, $CATALINA_BASE would be /usr/share/tomcat.
If your log4j configuration has not been changed, you'll find an appender named "cas" near the top of the file which is responsible for creating cas.log. It looks like this:
<appender name="cas" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="cas.log" />
<param name="MaxFileSize" value="512KB" />
<param name="MaxBackupIndex" value="3" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - %m%n"/>
</layout>
</appender>
Further down you'll find another appender named "fileAppender", which creates the perfStats.log file.
<appender name="fileAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="perfStats.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
See how the value for the File parameters is just a file name with no directory specified? The log files therefore get created in the $CATALINA_BASE directory. To get them into the Tomcat logs directory where you want them, just change the values to logs/cas.log and logs/perfStats.log.
Note that CAS only reads the log4j config at startup, so once you've made the change you'll have to either undeploy and redeploy CAS or bounce Tomcat for it to take effect.

Display only selected Log4j debug statements

Is it possible to display only those statements in console, which are having certain words.
For eq:
logger.debug ( "java: hello " );
logger.debug ( "groovy: hello " );
logger.debug ( "ruby: hello " );
Now, by doing some configuration or whatever, all statements which are starting with groovy: should display.
You want to use the log4j StringMatchFilter which is part of the "extras" package from apache logging.
Here is a quick example found online:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CustomAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="custom.log"/>
<param name="Append" value="true"/>
<param name="MaxFileSize" value="5000KB"/>
<param name="maxBackupIndex" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="Here is DEBUG" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
<root>
<appender-ref ref="CustomAppender"/>
</root>
</log4j:configuration>
What about create your customs Levels
public class Groovy extends Level
And then in the log properties file set those levels as your configuration
Hope this helps,
David.
One can use different loggers (say a logger for "java" messages and one for "groovy" messages). The Log4J configuration can be set with different levels for each logger.
You can read more here
One could use a tool to filter out messages. For Windows you could do this with BareTail. Filtering of messages is only possible with the pro (paid) version. Perhaps there are others tools that do the same job.
SLF4J markers are perhaps suitable for your purposes. All printing methods such as debug and info in org.slf4j.Logger admit a Marker as a first parameter. Moreover, logback-classic, a native SLF4J implementation, ships with a filter called MarkerFilter which I think does what you want.

Categories

Resources