Get log from LoggerFactory - java

It is possible so simple, but I've wasted already a lot of time to find any solution.
I have
package net.rubyeye.xmemcached;
...
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
public class XMemcachedClient implements XMemcachedClientMBean, MemcachedClient {
private static final Logger log = LoggerFactory
.getLogger(XMemcachedClient.class);
....
With Log4j I get all logs from apache-servicemix.
I've tried something like
log4j.logger.net.rubyeye.xmemcached.XMemcachedClient=All, xmemcachedLog
log4j.appender.xmemcachedLog=org.apache.log4j.RollingFileAppender
log4j.appender.xmemcachedLog.File=${karaf.data}/log/spring/xmemcachedLog.log
log4j.appender.xmemcachedLog.ImmediateFlush=true
log4j.appender.xmemcachedLog.maxFileSize = 10MB
log4j.appender.xmemcachedLog.maxBackupIndex = 10
log4j.appender.xmemcachedLog.layout=org.apache.log4j.PatternLayout
log4j.appender.xmemcachedLog.layout.ConversionPattern=%d{dd-MM-yyyy_HH:mm:ss} %-5p [%t] - %m%n
But I don't get anything. I want to get information about exception which I get on the 1335th line
key = this.preProcessKey(key);
Actually, it doesn't matter that I want to log exactly that class. In my application I also have other classes which have LoggerFactory.getLogger(...);
And the main question is
How to get logs from Logger log = LoggerFactory
.getLogger(SomeClass.class);
Now, my rootLogger looks like
# Root logger
log4j.rootLogger=info, out, sift, osgi:VmLogAppender
log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer

You should have a logback.xml somewhere which decide to show your log or not if you're on a java EE application.
Try to add this line of code into it:
<logger name="net.rubyeye.xmemcached" level="DEBUG"/>
It will activate DEBUGĀ logs for all the classes in this package.
If it still doesn't work maybe you don't have the file in your classpath and you might have to add it in the jvm parameter.

There is no problem in my logger. I've just hadn't any log.error() or log.smth() so I haven't got any lines in my files.
So it would work, for example, in that method inside XMemcachedClient
public void setTimeoutExceptionThreshold(int timeoutExceptionThreshold) {
if (timeoutExceptionThreshold <= 0) {
throw new IllegalArgumentException(
"Illegal timeoutExceptionThreshold value "
+ timeoutExceptionThreshold);
}
if (timeoutExceptionThreshold < 100) {
log.warn("Too small timeoutExceptionThreshold value may cause connections disconnect/reconnect frequently.");
}
this.timeoutExceptionThreshold = timeoutExceptionThreshold;
}
It shows me "Too small timeoutExceptionThreshold value may cause connections disconnect/reconnect frequently." in my ${karaf.data}/log/spring/xmemcachedLog.log when timeoutExceptionThreshold < 100

Related

Java log4j not working

I want to use log4j for generating the logs.
For this I am using the following code :
package com.idm.Test;
import org.apache.log4j.Logger;
public class log4jExample {
static Logger log = Logger.getLogger(log4jExample.class.getName());
public static void main(String[] args) {
log.info("Hello this is a debug message 1");
log.info("Hello this is a debug message 2");
log.info("Hello this is a debug message 3");
}
}
My log4j properties file is given below :
# Define the root logger with appender file
log=G:\\logs
log4j.rootLogger = DEBUG, FILE
# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=${log}\\log.out
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n
I want to generate log file inside
G:\logs\log.out
But the problem is that when I run this. There is no log file is created on this path.
When I already created one file into that location with log.out name and run again it is not showing me the logs inside this file.
I put my log4j.properties file inside com.idm.Test package.
You are using the the Java Util Logger in your code
import java.util.logging.Logger;
this is not the log4j logger. Fix your import and ensure that your configuration file will be found (either put in on the classpath or specifiy the location with the log4j.configuration system property - see here)
Note: OP edited question and uses the right import now...
By the way do not use log4j (1) anymore. It has reached its EOL and is not Java 9 ready.
Go with log4j2 (or other current logging frameworks) instead.
I did same like your code and properity, and log file was created.
In my case, log4j.properties is located in the root of class path.
i.e.)
classes/log4j.properties
classes/com/idm/Test/log4jExample
please, check the location of log4j.properties.
You should put log4j.properties in resource folder (source/main/resource), i think it will work correctly.
In case your project is java project (not maven project) i think you should change your code:
package com.idm.Test;
import org.apache.log4j.Logger;
public class log4jExample {
static Logger log = Logger.getLogger(log4jExample.class.getName());
public static void main(String[] args) {
**PropertyConfigurator.configure("yourPath/log4j.properties");**
log.info("Hello this is a debug message 1");
log.info("Hello this is a debug message 2");
log.info("Hello this is a debug message 3");
}
}

loading log4j.properties for log4j2

please check the attached image of project structure, let me know if i positioned log4j2.properties right.
also have a look at versions of jars I am using.
I wrote a simple program to print logs on console. in order to achieve this I wrote log4j2.properties file as follows.
Root logger option
log4j.rootLogger=INFO, file
log4j.appender.file= org.apache.logging.log4j.core.appender.ConsoleAppender
log4j.appender.file.Target=System.out
log4j.appender.file.Layout=org.apache.logging.log4j.core.layout.PatternLayout
log4j.appender.file.Layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Main program is as follows.(also shown in image)
package goldensource.track.logs;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.util.PropertiesUtil;
public class TestLogger {
private Logger logger;
private PropertiesUtil pu;
TestLogger()
{
System.setProperty("log4j.configurationFile","log4j2.properties");
logger = LogManager.getLogger(TestLogger.class);
logger.info("Yes I am there!");
logger.debug("I am debugging!");
logger.warn("giving you a warner!");
}
public static void main(String[] args) {
TestLogger z = new TestLogger();
}}
I have created a reference of PropertiesUtil but anyways I am not using it.
when I am executing this program nothing is shown on console. as I could make out, I am not able to load properties file properly.
suggest me any modifications or alternatives with examples.
Thanks in advance!
Without any feedback on the error you are getting, I can guess that one of the problems is with the file name. You should specify the absolute path to your log4j2.properties file when you are setting the system property:
System.setProperty("log4j.configurationFile","/absolute/path/to/log4j2.properties");
In this way the logger system will know exactly where to find your file.

Slf4j or Logback: Turn off logging for 1 unit test (or 1 thread)

I want to turn off logging for 1 unit test (which doesn't fail), so a stacktrace doesn't show up in the log. That stacktrace should be there in production runs because it's a failure-testing test.
The production code looks like this:
boolean failed = false;
for (int i = 0; i < 10; i++) {
try {
// Possible submits on Executor to run on other thread (not that it matters)
runTask(i);
} catch (RuntimeException e) {
// In the unit test, this pollutes the test log // BAD, MY PROBLEM
// In production, it shows up in the log immediately, before other tasks run // GOOD
logger.warn("Task failed. Stacktrace:", e);
failed = true;
}
}
if (failed) {
// The unit test checks if this exception is thrown,
// (it doesn't pollute the test log)
throw new IllegalStateException("at least 1 failed");
// In the real implementation, this also chains the first exception, to avoid eating the stacktrace
}
I have a unit test which tests that an executor throws an exception if at least 1 out of 10 tasks submitted to it fails. Because the executor can't fail when an inner exception occurs, it first runs the other tasks before throwing the outer exception. So when it catches the inner exception, it logs it, giving a stacktrace in the log. For QA, this is misleading, as the test logs show a stacktrace, despite that all tests succeeded. I want to get rid of that stacktrace in the test log (jira).
I believe there is no solution for slf4j as the supported frameworks might not support this function.
If you are using slf4j with a log4j binding you could achieve it as.
// get the logger you want to suppress
Logger log4j = Logger.getLogger("sub.optimal.package");
// keep the current level
Level previousLogLevel = log4j.getLevel();
// set the level to suppress your stacktrace respectively
log4j.setLevel(Level.WARN);
Find below an example how to configure the logger on method level. You need to have a different logger configured for which you change the logging level in production and in testing environment.
assume following directory structure and files
./Main.java
./slf4j-api-1.7.10.jar
./slf4j-log4j12-1.7.10.jar
./log4j-1.2.17.jar
./prod/log4j.properties
./testing/log4j.properties
./bin/
Main.java
package sub.optimal;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
Logger logger;
Logger loggerSuppressible;
{
logger = LoggerFactory.getLogger(this.getClass());
loggerSuppressible = LoggerFactory.getLogger("loggerSuppressible");
}
public void doSomeFoo() {
logger.info("logging from doSomeFoo");
}
public void doSomeStacktrace() {
try {
new File("..").renameTo(null);
} catch (NullPointerException npe) {
loggerSuppressible.error("something went wrong", npe);
}
}
public static void main(String[] args) {
Main main = new Main();
main.doSomeFoo();
main.doSomeStacktrace();
}
}
./prod/log4j.properties
log4j.rootCategory=info, console
# production setting
log4j.category.loggerSuppressible=info, console
log4j.additivity.loggerSuppressible=false
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=info
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n
./testing/log4j.properties
log4j.rootCategory=info, console
# testing setting
log4j.category.loggerSuppressible=fatal, console
log4j.additivity.loggerSuppressible=false
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=info
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n
compile
javac -cp ${classpath_logger} -d bin/ Main.java
** run in production**
java -cp bin/:prod/:${classpath_logger} sub.optimal.Main
** run in testing**
java -cp bin/:testing/:${classpath_logger} sub.optimal.Main
output production
2015-03-05 14:09:50,707 [main] INFO sub.optimal.Main - logging from doSomeFoo
2015-03-05 14:09:50,707 [main] ERROR loggerSuppressible - something went wrong
java.lang.NullPointerException
at java.io.File.renameTo(File.java:1386)
at sub.optimal.Main.doSomeStacktrace(Main.java:22)
at sub.optimal.Main.main(Main.java:32)
output testing
2015-03-05 14:09:50,847 [main] INFO sub.optimal.Main - logging from doSomeFoo
This might sound trivial, but have you thought about putting the logging call into an if-then block?
I'm pretty sure you pass the environment identifier to your application somehow (as an environment variable, for example). Now, it only takes a few minutes to create a utility class with a static method that decides whether the current environment is a testing environment or not.
Assuming that you can access the environment identifier as an environment variable, I'd go with something similar:
public class EnvironmentInfo {
private static final ENVIRONMENT_IDENTIFIER_PARAMETER = "env";
private static final Set<String> TEST_ENVIRONMENTS = ImmutableSet.of("test"); // this requires Guava
public static boolean isTestEnvironment() {
return TEST_ENVIRONMENTS.contains(System.getProperty(ENVIRONMENT_IDENTIFIER_PARAMETER));
}
}
And when you log, you'd simply go with:
if (!EnvironmentInfo.isTestEnvironment()) {
logger.warn("Task failed. Stacktrace:", e);
}

Creating multiple logs in log4j causing weird effects

I am trying to create multiple logs in Log4j, but I am facing a weird problem. Here's the log4j.properties and the code implementing it.
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILEALL
# Define the file appender
log4j.appender.FILEALL=org.apache.log4j.FileAppender
log4j.appender.FILEALL.File=${logfile.name}
# Define the layout for file appender
log4j.appender.FILEALL.layout=org.apache.log4j.HTMLLayout
#log4j.appender.FILEMAIN=org.apache.log4j.FileAppender
#log4j.appender.FILEMAIN.File=${logfilemain.name}
#log4j.appender.FILEMAIN.layout=org.apache.log4j.HTMLLayout
I have added the statement when running both and removed the original one
log4j.rootLogger = DEBUG, FILEALL , FILEMAIN
And this is the java code:
System.setProperty("logfile.name", savePath1);
// System.setProperty("logfilemain.name", savePath1);
logger = Logger.getLogger(HarishLog.class.getName());
PropertyConfigurator.configure("log4j.properties");
The code works perfectly fine till I make one log, but as soon as I enable the setting for 2nd log in either the properties or the javafile, nothing happens.
Besides I am unable to put a different name at
log4j.appender.FILEALL.File=${logfile.name}
it only works for logfile.name and logfilea.name, It doesn't work for any other name if I change it both in the javacode and the properties folder. Why is this???
Thank you
This works for me:
log4j.rootLogger = DEBUG, FILEALL, FILEMAIN
log4j.appender.FILEALL=org.apache.log4j.FileAppender
log4j.appender.FILEALL.File=${logfile.name}
log4j.appender.FILEALL.layout=org.apache.log4j.HTMLLayout
log4j.appender.FILEMAIN=org.apache.log4j.FileAppender
log4j.appender.FILEMAIN.File=${logfilemain.name}
log4j.appender.FILEMAIN.layout=org.apache.log4j.HTMLLayout
import org.apache.log4j.Logger;
public class LogTest {
public static void main(final String... args) {
System.setProperty("logfile.name", "logall.txt");
System.setProperty("logfilemain.name", "logmain.txt");
Logger logger = Logger.getLogger(LogTest.class.getName());
logger.info("hello");
}
}
If you're still having problems, try adding:
log4j.debug = true
to the beginning of your log4j.properties, and check the output messages.

log4j rollover at restart

I'm using a log4j FileAppender in my project to collect certain results. When my application restarts, I'd like to keep the previous resultsfile and start a new one. Is that possible?
For example:
Start application, write results to results.log
Application ends
Restart application, write results to results_1.log
...
I'v checked out the DailyRollingFileAppender, but that's not really what I need because that will automatically rollover on a certain date setting. I need to rollover when the application restarts.
Log4j2's RollingFileAppender has policy called OnStartupTriggeringPolicy.
As documentation states:
The OnStartupTriggeringPolicy policy causes a rollover if the log file is older than the current JVM's start time and the minimum file size is met or exceeded.
Example of xml configuration (only Policies):
<Policies>
<OnStartupTriggeringPolicy /> # restart on startup of JVM
<SizeBasedTriggeringPolicy size="20 MB" /> # restart file if log file reaches 20MB
<TimeBasedTriggeringPolicy /> # restart if currend date don't mach date in log file name
</Policies>
More informations and documentation:
https://logging.apache.org/log4j/2.x/manual/appenders.html#RollingFileAppender
How about having your application set the log file dynamically? You can do this by creating a file appender programatically when your application starts up and attaching it to your current logger.
For example, the following code will create new log files based on the current time. e.g. results_1336482894.log, results_1336486780.log
Date now = new Date();
FileAppender myFileAppender = new FileAppender();
myFileAppender.setName("myFileAppender");
myFileAppender.setFile("results_" + now.getTime() + ".log");
myFileAppender.setLayout(new PatternLayout("%d %-5p [%t]: %m%n"));
myFileAppender.setThreshold(Level.DEBUG);
myFileAppender.activateOptions();
Logger myLogger = Logger.getLogger("name of your logger"); //Or use getRootLogger() instead
myLogger.addAppender(myFileAppender);
I have solved this by writing my own appender:
import org.apache.log4j.RollingFileAppender;
/**
This appender rolls over at program start.
This is for creating a clean boundary between log data of different runs.
*/
public class RunRolledFileAppender
extends RollingFileAppender
{
public RunRolledFileAppender() { }
#Override
public void activateOptions() {
super.activateOptions();
super.rollOver();
}
#Override
public void rollOver() { }
}
Note the ugly disabling of rollOver() was necessary, since the MaxFileSize setting did not work and that Appender otherwise also rolled over every 10MB, which I didn't need.
You could use the ExternallyRolledFileAppender and the Roller classes to rollover the log file when your application starts up.
Here's an example class:
import org.apache.log4j.Logger;
import org.apache.log4j.varia.Roller;
public class Test {
private static final Logger log = Logger.getLogger(Test.class);
public static void main(final String[] args) {
Roller.main(new String[] {"localhost", "9999"});
log.debug("Started application!");
}
}
And an example log4j.properties file:
log4j.appender.file=org.apache.log4j.varia.ExternallyRolledFileAppender
log4j.appender.file.File=app.log
log4j.appender.file.Port=9999
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5p: %t: %c: %m%n
log4j.rootLogger=DEBUG, file
Do heed the warning in ExternallyRolledFileAppender:
Note that the initiator is not authenticated. Anyone can trigger a rollover. In production environments, it is recommended that you add some form of protection to prevent undesired rollovers.
If this does not suit your needs, it should be trivial to create your own similar Appender implementation.

Categories