I see that the class org.springframework.util.Log4jConfigurer is deprecated, but I could not find which class should be used as a replacement.
Specifically, I need Log4jConfigurer.initLogging.
Does anybody know which class/method I should use?
Thanks.
Only needed for non-default log4j initialization, for example with a custom config location or a refresh interval. By default, log4j will simply read its configuration from a log4j.properties or log4j.xml file in the root of the classpath.
String prop = System.getProperty("log4j.configuration");
if (prop == null) prop = "log4j.properties";
URL log4jConfig = Loader.getResource(prop);
if (log4jConfig.getProtocol().equalsIgnoreCase("file")){
PropertyConfigurator.configureAndWatch(log4jConfig.getFile().substring(1), 10000);
}else{
// cannot monitor if file changed because URL is not a file
}
Check this link.
Related
I am trying to figure out how to use the ExtendedLog4NetLogger.cs
to change the log file path dynamically at runtime or using the LoggingFacility?
This should be something similar to using log4net directly like this:
log4net.GlobalContext.Properties["LogName"] = logName;
How would I access the ExtendedLogger if I register log4net integration like this:
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
Update: I use the following code to register the Extended Logger
container.AddFacility<LoggingFacility>(LoggerImplementation.ExtendedLog4net).WithConfig(configFile).ToLog(Logger));
I get no runtime exceptions and the logger is not a null instance but I don't see the log file created at all using the global properties, I also set the config value to this for the appender: <file type="log4net.Util.PatternString" value="%property{LogName}" />
If I just set the file property in the config file to full path it does work. I am wondering if it is not working because configuration is done before setting the global variable.
extendedlogger.GlobalProperties["logName"] = logName;
To enable extended logger you need to do:
container.AddFacility<LoggingFacility>(f => f.LogUsing(LoggerImplementation.ExtendedLog4net));
1. How would I access the ExtendedLogger if I register log4net integration like this:
Using the dependency injection you can expect IExtendedLogger object in the place where you need it.
2. I am wondering if it is not working because configuration is done before setting the global variable.
That's right. You need to reconfigure log4net after setting a property.
Here is an example:
using Castle.Core.Logging;
using log4net.Config;
class MyClass {
private readonly IExtendedLogger _extendedLogger;
public MyClass(IExtendedLogger extendedLogger) {
_extendedLogger = extendedLogger;
}
public void MyFunction() {
_extendedlogger.GlobalProperties["logName"] = logName;
XmlConfigurator.Configure();
_extendedlogger.Error("my error message");
}
}
I am trying to load a class whose name is specified in a properties file. Here is the code for the same.
try {
Properties properties = new Properties();
InputStream in = MyAbstractFactory.class.getResourceAsStream("/some.properties");
properties.load(in);
String impl = properties.getProperty("key");
MyAbstractFactory factories = (MyAbstractFactory) Class.forName( impl ).newInstance();
return factories;
} catch (Exception e) {
return new DefaultFactoriesImpl();
}
This code is part of a jar file. the properties file is just outside the jar. Its unable to load the properties file and is loading DefaultFactoriesImpl instead. I know this happens when MyAbstractFactory.class.getResourceAsStream cant find the resource in the class path but that doesn't seem to be the case here.
Dir Structure:-
com
myjar.jar
some.properties
Command i am executing is "java -jar myjar.jar"
Any feedback on why this might be happening. Could this have something to do with Clasloaders? I'd like to add that when i run this code from within eclipse it seems pick up some.properties just fine.
Remove the leading slash from the argument you pass to getResourceAsStream().
Put the folder outside the JAR into the CLASSPATH when you execute the JAR. I don't know if the manifest CLASSPATH overrides the one you might pass using -cp. Play with it; one of them will work.
It's not finding your .properties file because it's not in the JVM CLASSPATH. When you do it properly, the JVM will find it.
I am trying to access the i18n properties file I'm using in my JSF application in code. (The idea is to have a page that displays its keys and values as a table actually.)
The project is a maven project, and in the src/resources/localization folder, and deployed in the war file in WEB-INF\classes\localization\
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
But the variable foo turns out to be null whatever I set the path variable to, /WEB-INF/classes/localization/stat_codes.properties, "localization.stat_codes.properties" etc. A similar question is here, but there is no helpful answer there as well.
The Class#getResourceAsStream() can take a path which is relative to the location of the Class which you're using there as starting point. So, for example, if the class is located in the com.example package and you request the path foo/filename.properties, then it will actually load the com/example/foo/filename.properties file. But if you use /foo/filename.properties, then it will actually load foo/filename.properties from the classpath root.
So, your code
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
will actually look for java/util/localization/stat_codes.properties file.
But in applications with a complex multiple classloader hierarchy, the one classloader isn't the other. The classloader which loaded the core Java classes does not necessarily have knowledge about files which are in the webapp's /WEB-INF/classes. So prefixing the path with / will not necessarily be the solution, it would still return null.
If you can guarantee that the current class is visible by the same classloader as the properties files (because they're in the same sub-root of the classpath, e.g. /WEB-INF/classes, then you should indeed use
String path = "/localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
But if at some point, the properties files will be externalized because of more easy maintenance/editing during runtime so that you don't need to rebuild/redeploy/restart the webapp whenever you want to edit the files, then the above line of code will likely fail as well. The externalized location would be only accessible by a different classloader. The canonical solution is to use the thread's context classloader as starting point instead, it has access to all resources in the classpath.
String path = "localization/stat_codes.properties";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream foo = loader.getResourceAsStream(path);
(note that this one cannot take a path starting with /, it's always relative to the common root)
See also:
Where to place and how to read configuration resource files in servlet based application?
ExternalContext#getResourceAsStream() returns null, where to place the resource file?
It seems that the culprit is the prop object, I supposed any object would work, but it has to be the current object (this) on which the method getClass() is invoked, it seems. Also, the path should start with a / since the localization directory resides in WEB-INF/classes.
String path = "localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
Is there a way to figure out where is Log4J picking the configuration file from?
I tried to change my log4j.xml and the changes were not reflected in Log4j behaviour. I deleted log4j.xml and funnily enough, Log4J is still working with the old behaviour. So it must be picking some configuration file which is available in my namespace. But the question is how can I figure out which one. Is there a way to do that? there are so many different dependencies on jars etc, so one of them must contains a log4j.xml or log4j.properties that is overriding my changes.
Any ideas?
When running your application you can set the system property -Dlog4j.debug. log4j will produce debug output in this case and tells you about how it resolves the path to the log4j.xml, e.g.:
log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader#11b86e7.
log4j: Using URL [file:/C:/develop/workspace/foobar/target/classes/log4j.xml] for automatic log4j configuration.
log4j: Preferred configurator class: org.apache.log4j.xml.DOMConfigurator
To set a path explicit use the system property -Dlog4j.configuration=file:c:/pathToFile as described here.
Activating -Dlog4j.debug like suggested by FrVaBe in his answer is a good solution. However, I wanted to print or log the location on startup without activating log4j's debug mode. I created a little util method, that is mostly a copy of log4j's default init routine, which returns the URL of the configuration file.
Maybe it's useful for someone else:
/**
* Get the URL of the log4j config file. This is mostly copied from org.apache.log4j.LogManager's default init routine.
*
* #return log4j config url
*/
public static URL getLog4JConfigurationUrl(){
/** Search for the properties file log4j.properties in the CLASSPATH. */
String override = OptionConverter.getSystemProperty(LogManager.DEFAULT_INIT_OVERRIDE_KEY, null);
// if there is no default init override, then get the resource
// specified by the user or the default config file.
if (override == null || "false".equalsIgnoreCase(override)){
String configurationOptionStr = OptionConverter.getSystemProperty(LogManager.DEFAULT_CONFIGURATION_KEY, null);
URL url;
// if the user has not specified the log4j.configuration
// property, we search first for the file "log4j.xml" and then
// "log4j.properties"
if (configurationOptionStr == null){
url = Loader.getResource("log4j.xml");
if (url == null){
url = Loader.getResource(LogManager.DEFAULT_CONFIGURATION_FILE);
}
} else {
try {
url = new URL(configurationOptionStr);
} catch (MalformedURLException ex) {
// so, resource is not a URL:
// attempt to get the resource from the class path
url = Loader.getResource(configurationOptionStr);
}
}
if (url == null)
throw new RuntimeException("log4j configuration could not be found!");
return url;
}
throw new RuntimeException("default init is overridden, log4j configuration could not be found!");
}
PS: if you know a way to ask log4j for it's currently used configuration file, let me know.
I am using log4j for logging, and a property file for configuration. Currently, my log files are too big (3.5 GB is too large for a log file). So think I need to use RollingFileAppender - but when I do so the log file continues to grow overly large. I believe I have just misconfigured it; does anyone have a working example of configuring RollingFileAppender?
For the record, my current configuration looks like this:
log4j.appender.MAIN_LOG.File=${catalina.base}/logs/webtop.log
log4j.appender.MAIN_LOG=org.apache.log4j.RollingFileAppender
log4j.appender.MAIN_LOG.layout=com.mycompany.util.log.Log4JSimpleLayout
log4j.appender.MAIN_LOG.DatePattern='.'yyyy-MM-dd
log4j.appender.MAIN_LOG.MaxFileSize=10MB
log4j.appender.MAIN_LOG.MaxBackupIndex=99
log4j.appender.MAIN_LOG.append=true
log4j.rootCategory=ALL, MAIN_LOG
An alternative to RollingFileAppender would also be a fine solution.
I believe I have just misconfigured it; does anyone have a working example of configuring RollingFileAppender?
This seems to work fine for me #mcherm. See below.
Are you sure that you are using the log4j.properties that you think you are? Try changing the .File to another path to see if log output goes to the new file. What version of log4j are you using? I'm running 1.2.15.
Hope this helps.
I created the following test program:
package com.j256.ormlite;
import org.apache.log4j.Logger;
public class Foo {
private static Logger logger = Logger.getLogger(Foo.class);
public static void main(String[] args) {
for (int x = 0; x < 10000000; x++) {
logger.error("goodness this shouldn't be happening to us right here!!!!");
}
}
}
My log4j.properties file holds:
log4j.appender.MAIN_LOG=org.apache.log4j.RollingFileAppender
log4j.appender.MAIN_LOG.File=${catalina.base}/logs/webtop.log
log4j.appender.MAIN_LOG.layout=com.j256.ormlite.Log4JSimpleLayout
log4j.appender.MAIN_LOG.MaxFileSize=10MB
log4j.appender.MAIN_LOG.MaxBackupIndex=5
log4j.appender.MAIN_LOG.append=true
log4j.rootCategory=ALL, MAIN_LOG
Notice that I removed the DatePattern which wasn't valid for my RollingFileAppender. My layout is:
package com.j256.ormlite;
import org.apache.log4j.spi.LoggingEvent;
public class Log4JSimpleLayout extends org.apache.log4j.Layout {
#Override
public String format(LoggingEvent event) {
return "log message = " + event.getMessage().toString() + "\n";
}
#Override
public boolean ignoresThrowable() {
return true;
}
public void activateOptions() {
}
}
Running with -Dcatalina.base=/tmp/ I get files in /tmp/logs/ which go up to index #5 and are 10mb in size. If I tune the MaxFileSize or the MaxBackupIndex, it adjusts appropriately.
Your issue might be with the fact that you are specifying a DatePattern.
The DatePattern is meant to be used with the DailyRollingFileAppender to specify the date that the log file should roll.
I don't believe it can be used in conjunction with the MaxFileSize and MaxBackupIndex attributes.
Log4j lets you roll files based on file size or date but not both.
When we need log files to be rolled on a daily basis, we should be using DailyRollingFileAppender instead of RollingFileAppender.
You do not need to specify the MaxFileSize limit instead only DatePattern is enough for rolling files based on frequency.
I have tried the below configuration in log4j.properties file for rolling log files every minute.
log4j.appender.infoAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.infoAppender.Threshold=INFO
log4j.appender.infoAppender.DatePattern='.' yyyy-MM-dd HH-mm
log4j.appender.infoAppender.File=C:/logs/info.log
Start by setting the -Dlog4j.debug JVM parameter. That prints out a few useful lines of debug information showing which config file it's found and is using, etc. That should give you some clues to what's going wrong.
See http://logging.apache.org/log4j/1.2/manual.html