I have the following log4j.properties file, for an application deployed in WebSphere Portal:
log4j.rootLogger=DEBUG, InfoAppender, DebugAppender
log4j.appender.InfoAppender=org.apache.log4j.RollingFileAppender
log4j.appender.InfoAppender.Threshold=INFO
log4j.appender.InfoAppender.File=C:/info.log
log4j.appender.InfoAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.InfoAppender.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.DebugAppender=org.apache.log4j.RollingFileAppender
log4j.appender.DebugAppender.Threshold=DEBUG
log4j.appender.DebugAppender.File=C:/debug.log
log4j.appender.DebugAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugAppender.layout.ConversionPattern=%d %p [%c] - %m%n
When I code, I define the logger at class level:
private static Logger logger = Logger.getLogger(IWannaLogThis.class);
And I log INFO messages with this:
logger.info(theObjectToLog);
When I deploy my application, the debug.log file gets everything I log with logger.debug() but ignores everything I write with logger.info(). On the other side, the info.log file keeps empty.
The weirdest thing is that in debug.log and info.log appears some INFO and DEBUG messages made by some JARS (like Hibernate Validator) I had in the classpath, but just ignores everything I try to log in my code.
Any ideas?
This is most likely a classloading-related problem. WebSphere Portal uses Log4J internally, so I'm guessing that you end up using WebSphere Portal's provided Log4J JAR file as well as its own Log4J properties.
You can verify that by adding the following to the JVM arguments of the server instance:
-Dlog4j.debug=true
And then inspect the SystemOut.log file. Log4J will spit out lots of tracing information about the configuration file(s) it reads.
The best way to avoid this is to do the following:
Bundle the Log4J JAR file with your application.
Associate a Shared Library with the server. In that Shared Library, place your Log4J configuration file.
As an alternative to step 2, you can bundle your Log4J configuration file with the application itself, however that would carry its own drawbacks (for example, having to repackage your application whenever you perform a Log4J configuration change).
Another common problem is that the JARs you have in your classpath also use log4j and also have their own appenders set. So depending on the settings that they use, and the packages that your classes reside in, this may lead to the problem you describe.
So:
Make sure that your package names are unique and not used by any of the third party libraries.
Check the log4j settings in all libraries in your classpath. They should not contain general settings which override yours.
Make sure your loggers use your log4j.properties (you can be sure if changes you make in your file affect your loggers as expected).
If you can, make sure that your log4j stuff loads last, in case any of the third party libs reset the configuration. They shouldn't, but who can stop them.
Normally, it should be one of these things. Post more explicit example if it doesn't work.
Good luck!
What I have done in the past is set specific logs for the classes I want to log. It sounds like you can try setting your root logger to INFO and see if that gets you the messages you want. Here's a little bit of my log4j property file. I set a logger for each class and assign it to my "data" appender, which defines the log layout. In the loggers I specify specific classes I want to log and set their Log level individually. Any class that logs that is not defined in the Loggers I have use the default log level for the rootCategory.
log4j.rootCategory=INFO, rollingFile, stdout
#GetData Loggers
log4j.logger.com.myapp.data=INFO, data
log4j.logger.com.myapp.data.SybaseConnection=DEBUG, data
log4j.logger.com.myapp.data.GetData=ERROR, data
# data appender
log4j.appender.data=org.apache.log4j.RollingFileAppender
log4j.appender.data.layout=org.apache.log4j.PatternLayout
log4j.appender.data.File=c\:\\Program Files\\MyApp\\logs\\MyApp-data.log
log4j.appender.data.Append=true
log4j.appender.data.layout.ConversionPattern=[%d{ISO8601}]%5p%6.6r[%t]%x - %C.%M(%F:%L) - %m%n
you root logger opens the log properties in the debug mode,
use INFO instead of DEbug in the first line of your properties file.
Related
I use websphere 9 application server to deploy war's and ear's, and use java.util.logging to generate logs into applications. I try to use properties file to configure the FileHandler of the LogManager, but websphere write ALL other logs on my file.
I not use log4j because i can't set log levels at runtime.
Is possible make differents file logs by application over websphere with java.util.logging ?
This is my properties file Logger.properties
handlers= java.util.logging.FileHandler
#java.util.logging.ConsoleHandler.level = INFO
#java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Set the default formatter to be the simple formatter
java.util.logging.FileHandler.formatter =java.util.logging.SimpleFormatter
# Use UTF-8 encoding
java.util.logging.FileHandler.encoding = UTF-8
# Write the log files to some file pattern
java.util.logging.FileHandler.pattern = C:/Users/pmendez/Documents/Log/testLogs.log
# Limit log file size to 5 Kb
java.util.logging.FileHandler.limit = 5000
# Keep 10 log files
java.util.logging.FileHandler.count = 10
#Customize the SimpleFormatter output format
java.util.logging.SimpleFormatter.format = %d [%t] %-5p (%F:%L) - %m%n
I try to use properties file to configure the FileHandler of the LogManager, but websphere write ALL other logs on my file.
Per your logging.properties you are attaching the FileHandler to the root logger. It would be expected to see log records from WebSphere because by default Logger::setUseParentHandlers is set to true.
Is possible make differents file logs by application over websphere with java.util.logging ?
You have to do one of the following:
Attach your FileHandler to the root logger of your application so the FileHandler is not attached to parent of the WebSphere application. Say application package is com.my.app.rules you can add entry of tocom.my.app.rules.handlers=java.util.logging.FileHandler and remove the attachment to the root logger. Next you demand the logger from code and pin it to memory so this package becomes the new root logger of your application code.
Create java.util.logging.Filter and install it on the FileHandler.
Turn off the logging for WebSphere. You can do this by setting the root logger to off and forcing all of your loggers to say info.
.level=OFF
com.my.app.rules.class1.level=INFO
com.my.app.rules.class2.level=INFO
com.my.app.rules.class3.level=INFO
It's possible set one FileHandler by app ?
The default java.util.logging.LogManager only supports one set of FileHandler settings. You can attach instances to various loggers but it doesn't allow for instances with different settings via the logging.properties. However, the LogManager does support per the documentation:
A property "config". This property is intended to allow arbitrary configuration code to be run. The property defines a whitespace or comma separated list of class names. A new instance will be created for each named class. The default constructor of each class may execute arbitrary code to update the logging configuration, such as setting logger levels, adding handlers, adding filters, etc.
So what you need to do is bundle a configuration class with your application that performs the needed FileHandler and logger configuration and modify your logging.properties to load it. One issue with this approach is that the LogManager can only see classes from the system class loader.
From jmehrens answer you can see it might be a bit difficult. Maybe you should consider switching logging to High Performance Extensible Logging (HPEL). It is just setting in the application server, so no changes in the applications code.
Then you could query logs for the given application using command line tool:
logViewer.sh -includeExtensions appName=PlantsByWebSphere
This would be much easier, if it fits your purpose. Moreover, generating separate log files is now not recommended, if you plan to move your apps in the future into containers/cloud or refactor them into microservices.
My solution to this isue was create a PersonalFileHandler to use on all Logger's. Properties are read from properties file called "Logger.properties", and invoque read this programmatically, same like this:
//Read config file
LogManager.getLogManager().readConfiguration(LoggerJUL.class.getResourceAsStream("/Logger.properties"));
//Add handler to logger
Logger.getLogger(clazz)).addHandler(new PersonalFileHandler());
PersonalFileHandler extends FileHandler, and properties are set by configure method on FileHandler class on runtime.
I'm having some trouble configuring proper logging in Eclipse Scout framework. My claims aren't that high as I only want to be able to set different log levels for different parts of my program in a configuration/properties/XML file.
The logging configuration in the config.ini of my Scout server plugin currently looks like this:
eclipse.consoleLog=true
org.eclipse.scout.log=eclipse
org.eclipse.scout.log.level=INFO
So as you can see this is the default logging configuration using Eclipse logging. It works fine for logging at a global level. The only thing I would like to do is to write something like this to set the different log levels:
packagename.ClassName=LOGLEVEL
As this is a very basic logging use case I think there must be some easy way to do this in Scout. Otherwise I would appreciate some help how to configure log4j, JUL or others for the use with Scout. The Eclipse Scout Wiki hasn't helped me so far. I created the example logger fragment to the host plugin 'org.eclipse.scout.commons' and removed the logging configuration lines from my config.ini but nothing happens. I'm also not sure where to put the log4j.poperties or how this is done otherwise.
I'm a bit ashamed for being unable to figure out such a basic problem, but would be very happy about some quick help.
I can tell you how to configure the logging if you choose the java logger (config.ini: org.eclipse.scout.log=java).
For the eclipse logger, I barely found any information at all.
Now, to configure the java (JUL) logging: You can do this in a file called logging.properties.
You can configure the logging by specifying the configuration file in your product:
Create your configuration file - say logging.properties inside the folder where your product file (for server or client respectively) is located. Typically this is in a folder named 'products'.
Open your product file and go to the "Launching" tab and specify your logging configuration file in the "VM Arguments" tab. Use the "java.util.logging.config.file" system property to do so:
-Djava.util.logging.config.file="${resource_loc:/com.yourapp.server/products/logging.properties}"
Now, you should be able to specify the log levels in your new logging.properties file:
### Root level of your application, all below are ignored
.level=INFO
### Handlers
handlers=java.util.logging.ConsoleHandler
### Handler properties
java.util.logging.ConsoleHandler.level=FINEST
### Override the logging level for certain classes
com.yourapp.server.SomeService.level=FINE
Alternatively, you can also use a class to initialize the logging with the java.util.logging.config.class option. See this wiki page for a detailed example.
Also, when building a WAR file, you might be interested in this answer.
I'm currently working on a project that uses log4j.
I'm running a testcase (junit) and would like to set the log level to trace so that I can see if all the values are correct. Classes that use logging in the project contain a line like the following:
private static final Log LOG = LogFactory.getLog(MatchTaskTest.class);
and use a like like this to do the actual debugging
LOG.trace("value");
I have never used log4j before, does anybody know how I can change the log level just for the testcase, preferably simply by defining a parameter in eclipse's run configuration dialog.
Using another configuration file
Perhaps you could point to another configuration file.
java -Dlog4j.configuration=config file yourApp
Where:
config, you file of configuration, e.g. log4j.properties or log4j.xml.
file, the log file, e.g. myApp.log
yourApp, you app, e.g. MyAppGUI
Or you can use a class
java -Dlog4j.configurationClass=config class yourApp
Where:
config, you file of configuration, e.g. log4j.properties or log4j.xml.
class, any customized initialization class, like LogManager, should implement
the org.apache.log4j.spi.Configurator
yourApp, you app, e.g. MyAppGUI
You can see more in Apache log4j 1.2 - Short introduction to log4j on Default Initialization Procedure section.
Modifying the level programmatically
Moreover, you can also use the methods that offers the Logger class, like public void setLevel(Level level), e.g.:
Logger.getRootLogger().setLevel(Level.TRACE);
Since you want only for testing purposes, you could use them. But it is recommended not to use in client code because they overwrite the default configuration parameters in hard coded. The best way is to use an external configuration file.
In your junit class put:
Logger.getRootLogger().setLevel(Level.TRACE);
somewhere before the execution of the tested method. It will set the threshold level of the root logger to TRACE.
If you're using Maven, you can have two log4j configuration files:
one in src/main/resources, containing your production logging config
one in src/test/resources, containing your test-time logging config
Maven will automatically use the latter at test time, and bundle the former into your artifact (JAR, WAR, etc) so that it's used in production. You don't have to mess around with command line switches or anything.
I don't think this is possible.
The config file is going to let you configure what log messages actually surface in the log, not what level each message is going be logged at. This makes sense - the config should not affect the level of the message.
The javadoc has a method for each log level and a generic log method, which takes in a priority, so I'm not sure there's even a default to be set.
You can set a config file explictly on the command line via -Dlog4j.configuration=<FILE_PATH>, so you could set up a specific config for that test case.
I have no idea why some of the above didn't work for me. (I don't want to write config file). following works for me
Logger log1 = Deencapsulation.getField(Some.class,"logger");
log1.setLevel(Level.DEBUG);
NB that the log4j2.properties file may include the line
filter.threshold.level = debug
You can waste an entire afternoon trying to figure out why your LOG.trace() statements aren't outputting anything!
I actually put it in the #Before method. But I believe it could (and should) be placed in the #BeforeClass.
If you set it in the class body you'll get compiler errors.
By default slf4j, when using with jdk (slf4j-jdk14-1.6.1.jar), does not log debug messages.
How do I enable them?
I can’t find info neither in the official docs, the web or here on how to enable it.
I found some info on (failed though) creating a file in %JDK_HOME%/lib and defining the level there, in a config file.
However, I would like to define the level at compile-/run-time so I can both run and debug my app from my IDE with different logging levels.
Isn’t there some environment variable I can set, or VM arg?
Why do you think it does not log DEBUG messages?
If you mean that your log.debug(String) logging calls do not end up in java.util.logging log files, then I guess you have to configure the logging.properties configuration file to allow log messages at FINE level.
If you do not want to mess with the global %JRE_HOME%/lib/logging.properties, then you can just pass in -Djava.util.logging.config.file=logging.properties on the command line - this will force the logging system to look for that configuration file in the current directory.
Or use some other (programmatic) way to configure java.util.logging, see below for tutorial.
This has nothing to do with configuring SLF4J; in fact, SLF4J does not have any configuration, everything is configured by simply swapping JAR files.
For your reference:
JDK14LoggerAdapter
Java Logging API tutorial
If you are using slf4j SimpleLogger implementation read this.
There you can see that simpleLogger use INFO as default log level. You can change it by using a system property. This is usefull for non-production evironments:
static {
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "trace");
}
You can add -Dorg.slf4j.simpleLogger.defaultLogLevel=debug to the VM options.
I just put my logging.properties file in my applications WEB-INF/classes file (or use the command line argument identified by Neeme Praks if you're not deploying in a war), and have the properties file open in eclipse so I can fine tune it to log the packages and at the level I'm interested in.
In the logging.properties file, you need to make sure that both the logger level and the handler level are set to the level you want. For example, if you want your output to go to the console, you need to have at least the following:
#logging.properties file contents
#Define handlers
handlers=java.util.logging.ConsoleHandler
#Set handler log level
java.util.logging.ConsoleHandler.level=FINE
#Define your logger level
com.company.application.package.package.level=FINE
#Assign your handler to your logger
com.company.application.package.package.handlers=java.util.logging.ConsoleHandler
You mentioned the slf4j-jdk14-1.6.1.jar. This provides the slf4j binding to java.util.logging. You need to have that in your classpath, but make sure you also have the slf4j api (slf4j-api-1.7.12.jar) in your classpath as well.
I find the example logging.properties file in this link useful for creating a variety of loggers and handlers, to give you fine-grained control over what logs go to the console, and what logs go to a file:.
And here's the slf4j manual.
if you are using lombok Slf4j
package com.space.slf4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* #author anson
* #date 2019/6/18 16:17
*/
#Slf4j
#RestController
public class TestController {
#RequestMapping("/log")
public String testLog(){
log.info("######### info #########");
log.debug("######### debug #########");
log.error("######### error #########");
return null;
}
}
application.yml
logging:
level:
root: debug
In runtime with the default configuration you can enable it with this code:
public class MyTest {
static {
Logger rootLogger = Logger.getLogger("");
rootLogger.setLevel(Level.ALL);
rootLogger.getHandlers()[0].setLevel(Level.ALL);
}
I'm using this code inside TestNG Unit.
I have an embedded tomcat app and whenever I start it up I see this error printed to the console twice:
Unable to configure the logging system. No log.properties was found.
It seems stupid, but I've done some googling and searched stackoverflow and can't seem to find someone experiencing this problem.
My main class Looks roughly like this:
public class AuthServerEntryPoint {
static {
org.apache.log4j.PropertyConfigurator.configure("conf/log4j.properties");
}
public static void main(String[] args) {
// ...
}
"conf/log4j.properties" contains a seemingly valid configuration:
log4j.appender.mainAppend=org.apache.log4j.ConsoleAppender
log4j.appender.mainAppend.layout=org.apache.log4j.PatternLayout
log4j.appender.mainAppend.layout.ConversionPattern=%d %p [%t] %c -- %m%n
log4j.appender.fileAppend=org.apache.log4j.FileAppender
log4j.appender.fileAppend.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppend.layout.ConversionPattern=%d %p [%t] %c - %m%n
log4j.appender.fileAppend.file=logs/myservice.log
log4j.rootLogger = info, fileAppend
log4j.logger.com.mycompany.myservice = debug, fileAppend
And the logging actually does work - i.e., logs are correctly written to myservice.log. So what gives?
Thanks!
-Carl
By embedded Tomcat app, do you mean that you are starting Tomcat from Java code and are using the class org.apache.catalina.startup.Embedded?
If yes, my guess is that Tomcat might not be able to find its logging configuration file that is set up in catalina.sh (or equivalent) when using the scripts:
LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
The odd part is that this file is called logging.properties, not log.properties, so I'm really not sure. I didn't check Tomcat sources though, maybe they are doing some kind of black magic in there.
Could you just try to rename $CATALINA_BASE/conf/logging.properties into log.properties (or not) and to put it on the classpath of your app (or to set -Djava.util.logging.config.file)?
By default, log4j will look for a logging properties file on the classpath. Put your webapp's logging properties config file into its WEB-INF/classes directory; e.g.
$CATALINA_HOME/webapps/<yourApp>/WEB-INF/classes/log4j.properties
This is the simple approach to getting a webapp to use Log4j is recommended by the referenced documentation. And it is the approach I use myself for webapp logging.
There are various other ways to configure Log4j logging on Tomcat as well. It is possible that your Tomcat has been (partly) configured to use one of them, but something has not been done quite right.
Configuring Tomcat' log4j logging via the system properties is an option that avoids figuring out where log4j is looking ... and what is going wrong. But you are then stuck with creating/using a custom launch script or having to remember to set environment variables before launching Tomcat.
References:
Configuring logging on Tomcat 5.5
Configuring logging on Tomcat 6
The "Default Initialization under Tomcat" section of the Log4j Manual