is it possible to override the "File" property of an appender that has been configured in the log4j.properties without creating a new appender?
And if so - how?
This is the situation: I have two apenders, A1 is a ConsoleAppender and A2 is a FileAppender. A2's "File" points a generic error.log:
log4j.appender.A2.File=error.csv
This appender only logs error-level events or worse through
log4j.appender.A2.Threshold=error.
Now I want those errors to be written in different files depending on which class caused the error, as there are several classes that instances are being created of.
Being able to see which class created the error(s) fast would be of great help, as it is a lot more helpful then skimming through the error.log looking for the class-tags.
So my idea was to override the "File" property e.g. in the constructors of these newly created classes, so they log errors in different files.
Thanks a lot in advance!
For changing log4j properties on runtime visit this link
http://alperkaratepe.wordpress.com/2010/01/16/how-to-change-log4j-properties-at-runtime/
private void updateLog4jConfiguration(String logFile) {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream( "/log4j.properties");
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("Error: Cannot laod configuration file ");
}
props.setProperty("log4j.appender.FILE.file", logFile);
PropertyConfigurator.configure(props);
}
Old question (well indexed in google). In addition to OP's requirement, adding additional methods iv'e read about to manipulate log4j.properties
Modify loaded log4j.properties in runtime
private void updateLog4jConfiguration(String logFile) {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream( "/log4j.properties");
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("Errornot laod configuration file ");
}
props.setProperty("log4j.appender.FILE.file", logFile);
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
}
full example is in this article
Setting log4j.properties in runtime
Can be done manually
Properties properties = new Properties();
properties.setProperty("log4j.logger.org.hibernate", "ERROR");
// ...
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
Or by loading a different properties file
Properties properties = new Properties();
properties.load(new FileInputStream("/etc/myapp/properties/custom-log4j.properties"));
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
VM Option
You can tell log4j to load a different file using log4j.configuration VM option
java -Dlog4j.configuration=file:///etc/myapp/properties/custom-log4j.properties
if you choose this option, it must be provided in the execution line
Related
I have a config.properties file that i want to update during runtime (for example, if the app receives a certain rest call, it updates the config properties).
Is this doable in java? or we can't change the config file on runtime?
thanks
In case you are using Java's Properties class, you can easily do it like this:
final Properties config = new Properties();
You can load a config file to your in-memory config like this:
final File f = new File("config.properties");
if(!f.exists) {
f.createNewFile();
}
final InputStream in = new FileInputStream(in);
config.load(in); //loads the config into the Properties object
in.close();
And if you wish to save the Properties back to a file, you can do:
final OutputStream out = new FileOutputStream(f);
config.save(out, "Some config comments...");
out.close();
You would probably need to wrap this in a try-catch block, but that's basically it.
This is possible, i assume you're using the Properties API? http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
You can use the store method specifying an OutputStream
logback uses Joran internally, which enabled logback to read configuration files and update them "on the fly" when their content changes. I used this functionality in 2011 and as far as I know Joran still is part of logback.
You could do something like this:
ruleMap = new HashMap<Pattern, Action>();
SetProfileParameterAction profile = new SetProfileParameterAction();
ruleMap.put(new Pattern("*/profile"), new AddProfileAction());
ruleMap.put(new Pattern("*/profile/description"), profile );
ruleMap.put(new Pattern("*/profile/link"), profile);
SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);
simpleConfigurator.setContext(context);
try {
simpleConfigurator.doConfigure(cfgFile);
} catch (JoranException e) {
log.error( "failed ...", e);
StatusPrinter.print(context);
}
Please note: this is just a non-complete cut-down version of my code but if Joran works for you this example will give you a hint in which direction to go ...
I use log4j for logging in my app. In every class I need to log something I have the following:
Properties props = new Properties();
try {
props.load(new FileInputStream("/log4j.properties"));
} catch (Exception e){
LOG.error(e);
}
PropertyConfigurator.configure(props);
log4j.properties is placed to the folder /src/main/resources/
the path /log4.properties is given by IDEA as copy reference. When I start my app it it shows the FileNotFoundException
Don't use FileInputStream.
The java.io and its consorts work with the current working directory i.e the directory from which the JVM is executed and not the code workspace.
to illustrate this consider the following piece of code
class ReadFrmFile {
public static void main(String args[]) {
FileInputStream fin = New FileInputStream("intemp.txt");
}
}
If the code is executed from C:\TEMP , the intemp.txt is expected to be in the working directory(C:/TEMP) in this case. If not this will throw the FileNotFoundException. The path of the file names are always absolute and not relative.
To avoid hardcoding the best way would be to place all the required files in the classpath and load them using getResourceAsStream().
Properties props = new Properties();
try {
InputStream inStream = **YOUR_CLASS_NAME**.class.getResourceAsStream("/log4j.properties");
props.load(inStream);
} catch (Exception e){
LOG.error(e);
}
PropertyConfigurator.configure(props);
log4j, by default, looks for the log4j.properties file in the classpath, so you don't need to use the class PropertyConfigurator, ony if the file doesn't exist in the root of the classpath.
In the Spring MVC + Log4j Integration Example, you will see:
I am aware of two ways to read a .properties file:
1- System.getProperties.load(Inputstream for .properties file);
2- Creating a new Properties object and then calling load(Inputstream for .properties file);
In first approach, are we going to store values of .properties file in the System object. Is it utilizing more resources?
Would like to know which is the best way to do it or apart from above two ways, if there is any other best way, please let me know.
Thanks.
Depends on what the properties file represents. If it represents system properties which needs to override/supply some default system properties, then go for the first approach. But if it represents application-specific properties (which is more often the usual case), then go for the second approach.
IMO, it is a BAD idea to load application properties into the System properties object. If someone puts bogus property values into the file you are loading, this could cause all sorts of obscure failures. For example, setting "java.home" to a bogus value will cause JavaMail to fail, and setting one of the "*.separator" properties could cause all sorts of things to behave strangely.
If your application really needs to "overlay" the system properties, then it would be better to do this:
Properties props = new Properties(System.getProperties());
props.load(someInputStream);
If it doesn't, then just load the Properties as follows:
Properties props = new Properties();
props.load(someInputStream);
If for some reason you need to override values in the System Properties object itself, then you should do it much more carefully / selectively.
we will read properties files using the URl...
Properties props = new Properties();
try
{
java.net.URL url = Thread.currentThread().getContextClassLoader().getResource(fileName);
java.net.URL url2 = ClassLoader.getSystemResource(fileName);
props.load(url.openStream());
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return props;
I have a stupid java logging problem: I'm loading the logging configuration from my app configuration file - but it just doesn't log anything after reading the file (which looks pretty much like the examples you will find on the net except for the additional application configuration - removing this also doesn't help). The "initializing..." log line appears just fine, but the "starting app" and any further messages are neither logged to the console, nor is the logfile ever created. What am I missing here?
The Logger code looks like this:
...
Logger log = Logger.getLogger("myApp");
log.setLevel(Level.ALL);
log.info("initializing - trying to load configuration file ...");
Properties preferences = new Properties();
try {
FileInputStream configFile = new FileInputStream("/path/to/app.properties");
preferences.load(configFile);
LogManager.getLogManager().readConfiguration(configFile);
} catch (IOException ex)
{
System.out.println("WARNING: Could not open configuration file");
System.out.println("WARNING: Logging not configured (console output only)");
}
log.info("starting myApp");
...
And this is the configuration file:
appconfig1 = foo
appconfig2 = bar
# Logging
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level = ALL
# File Logging
java.util.logging.FileHandler.pattern = %h/myApp.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = INFO
# Console Logging
java.util.logging.ConsoleHandler.level = ALL
you can set your logging configuration file through command line:
$ java -Djava.util.logging.config.file=/path/to/app.properties MainClass
this way seems cleaner and easier to maintain.
Okay, first intuition is here:
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level = ALL
The Java prop file parser isn't all that smart, I'm not sure it'll handle this. But I'll go look at the docs again....
In the mean time, try:
handlers = java.util.logging.FileHandler
java.util.logging.ConsoleHandler.level = ALL
Update
No, duh, needed more coffee. Nevermind.
While I think more, note that you can use the methods in Properties to load and print a prop-file: it might be worth writing a minimal program to see what java thinks it reads in that file.
Another update
This line:
FileInputStream configFile = new FileInputStream("/path/to/app.properties"));
has an extra end-paren. It won't compile. Make sure you're working with the class file you think you are.
I have tried your code in above code don't use
[preferences.load(configFile);]
statement and it will work. Here is a running sample code
public static void main(String[] s) {
Logger log = Logger.getLogger("MyClass");
try {
FileInputStream fis = new FileInputStream("p.properties");
LogManager.getLogManager().readConfiguration(fis);
log.setLevel(Level.FINE);
log.addHandler(new java.util.logging.ConsoleHandler());
log.setUseParentHandlers(false);
log.info("starting myApp");
fis.close();
} catch(IOException e) {
e.printStackTrace();
}
}
Logger log = Logger.getLogger("myApp");
log.setLevel(Level.ALL);
log.info("initializing - trying to load configuration file ...");
//Properties preferences = new Properties();
try {
//FileInputStream configFile = new //FileInputStream("/path/to/app.properties");
//preferences.load(configFile);
InputStream configFile = myApp.class.getResourceAsStream("app.properties");
LogManager.getLogManager().readConfiguration(configFile);
} catch (IOException ex)
{
System.out.println("WARNING: Could not open configuration file");
System.out.println("WARNING: Logging not configured (console output only)");
}
log.info("starting myApp");
this is working..:)
you have to pass InputStream in readConfiguration().
Are you searching for the log file in the right path:
%h/one%u.log
Here %h resolves to your home : In windows this defaults to :
C:\Documents and Settings(user_name).
I have tried the sample code you have posted and it works fine after you specify the configuration file path (logging.properties either through code or java args) .
i am writing standalone java app for production monitoring. once it starts running the api is configured for default values which is set in .properties file. in running state the api's configuration can be changed and the .properties file should be updated accordingly. is there a way to achieve this ? or are there any other approaches to implement this ?
Thanks in advance
The Java Properties class (api here) specifies "load" and "store" methods which should do exactly that. Use FileInputStream and FileOutputStream to specify the file to save it into.
You could use a very simple approach based on the java.util.Properties class which has indeed a load and store methods that you can use in conjunction with a FileInputStream and FileOutputStream:
But actually, I'd recommend to use an existing configuration library like Commons Configuration (amongst others). Check the Properties Howto to see how to load, save and automatically reload a properties file using its API.
I completely agree that Apache Commons Configuration API is really good choice.
This example update properties at runtime
File propertiesFile = new File(getClass().getClassLoader().getResource(fileName).getFile());
PropertiesConfiguration config = new PropertiesConfiguration(propertiesFile);
config.setProperty("hibernate.show_sql", "true");
config.save();
From the post how to update properties file in Java
Hope this help!
java.util.Properties doesn't provide runtime reloading out-of-the-box as far as I know.
Commons Configuration provides support for reloading configuration at runtime. The reload strategy can be configured by setting a ReloadingStrategy on the PropertiesConfiguration object. It also offers various other useful utilities for making your application configurable.
In addition to the load and store method of the Properties class, you can also use the Apache Commons Configuration library, which provides functions to easily manipulate configuration files (and not only .properties files).
Apache common configuration API provided different strategies to reload property files at run time. FileChangedReloadingStrategy is one of them. Refer this link to see an example for property file reloading at run time using FileChangedReloadingStrategy.
Try this:
// Write in property file at runtime
public void setValue(String key, String value) {
Properties props = new Properties();
String path = directoryPath+ "/src/test/resources/runTime.properties";
File f = new File(path);
try {
final FileInputStream configStream = new FileInputStream(f);
props.load(configStream);
configStream.close();
props.setProperty(key, value);
final FileOutputStream output = new FileOutputStream(f);
props.store(output, "");
output.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// Read same file
public String getValue(String key) {
String value = null;
try {
Properties prop = new Properties();
File f = new File(directoryPath+"/src/test/resources/runTime.properties");
if (f.exists()) {
prop.load(new FileInputStream(f));
value = prop.getProperty(key);
}
} catch (Exception e) {
System.out.println("Failed to read from runTime.properties");
}
return value;
}