I want to put all my config files in a /config subfolder of my application directory. Log4j is expecting the log4j.properties file in the root folder of my application. Is there a way to tell log4j where to look for the properties file?
Yes, define log4j.configuration property
java -Dlog4j.configuration=file:/path/to/log4j.properties myApp
Note, that property value must be a URL.
For more read section 'Default Initialization Procedure' in Log4j manual.
You can use PropertyConfigurator to load your log4j.properties wherever it is located in the disk.
Example:
Logger logger = Logger.getLogger(this.getClass());
String log4JPropertyFile = "C:/this/is/my/config/path/log4j.properties";
Properties p = new Properties();
try {
p.load(new FileInputStream(log4JPropertyFile));
PropertyConfigurator.configure(p);
logger.info("Wow! I'm configured!");
} catch (IOException e) {
//DAMN! I'm not....
}
If you have an XML Log4J configuration, use DOMConfigurator instead.
Use the PropertyConfigurator: PropertyConfigurator.configure(configFileUrl);
Refer to this example taken from -
http://www.dzone.com/tutorials/java/log4j/sample-log4j-properties-file-configuration-1.html
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class HelloWorld {
static final Logger logger = Logger.getLogger(HelloWorld.class);
static final String path = "src/resources/log4j.properties";
public static void main(String[] args) {
PropertyConfigurator.configure(path);
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
}
}
To change the logger levels - Logger.getRootLogger().setLevel(Level.INFO);
In Eclipse you can set a VM argument to:
-Dlog4j.configuration=file:///${workspace_loc:/MyProject/log4j-full-debug.properties}
This is my class : Path is fine and properties is loaded.
package com.fiserv.dl.idp.logging;
import java.io.File;
import java.io.FileInputStream;
import java.util.MissingResourceException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class LoggingCapsule {
private static Logger logger = Logger.getLogger(LoggingCapsule.class);
public static void info(String message) {
try {
String configDir = System.getProperty("config.path");
if (configDir == null) {
throw new MissingResourceException("System property: config.path not set", "", "");
}
Properties properties = new Properties();
properties.load(new FileInputStream(configDir + File.separator + "log4j" + ".properties"));
PropertyConfigurator.configure(properties);
} catch (Exception e) {
e.printStackTrace();
}
logger.info(message);
}
public static void error(String message){
System.out.println(message);
}
}
You must use log4j.configuration property like this:
java -Dlog4j.configuration=file:/path/to/log4j.properties myApp
If the file is under the class-path (inside ./src/main/resources/ folder), you can omit the file:// protocol:
java -Dlog4j.configuration=path/to/log4j.properties myApp
Related
I'm using log4j2 (version 2.5) in Java 8.
I need a log file with only one line. Therefore for each writing, the previous line if it exists must be overwritten by the new line.
log4j.properties:
name=testLoggerOneLine
appenders=console, logFile
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=[%-5level] %d{yyyy-MM-dd'T'HH:mm:ss.SSSZ}
[%t] %c{1} - %msg%n
appender.logFile.type=File
appender.logFile.name=LOGFILE
appender.logFile.fileName=C:/Users/mggl/workspace/Test/logs/Test.log
#appender.logFile.immediateFlush=true
#appender.logFile.append=false
#appender.logFile.createOnDemand=false
appender.logFile.layout.type=PatternLayout
appender.logFile.layout.pattern=%msg%n
loggers=logFile
logger.logFile.name=Test
logger.logFile.level=debug
logger.logFile.appenderRefs=logFile
logger.logFile.appenderRef.logFile.ref=LOGFILE
logger.logFile.additivity=false
rootLogger.level=debug
rootLogger.appenderRefs=stdout
rootLogger.appenderRef.stdout.ref=STDOUT
Dummy code:
package Test.loggingTest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class OneLineLog
{
public static void main( String[] args )
{
Logger logger = LogManager.getLogger("testLoggerOneLine");
logger.info("first writing");
logger.info("second writing");
logger.info("third writing");
}
}
In Test.log there must be written only the last logging info.
The option append with value false does the job for a bunch of logging information at each application start. I want to do the same for each line without restarting the application.
Any clue or suggestion is appreciated. Thanks in advance.
I solved the problem using append and immediateFlush options (set to false and true respectively) in log4j.properties and forcing the rollover on the appender associated with the logger. I used the snippet written by rgoers in this discussion:
How to rotate a log4j log manually
log4j.properties:
name=Test
appenders=console, logFile
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} - %msg%n
appender.logFile.type=RollingFile
appender.logFile.name=LOGFILE
appender.logFile.fileName=.../logs/Test.log
appender.logFile.filePattern=.../logs/%d{yyyyMMdd'T'HH:mm:ss.SSSZ}-Test.log.gz
appender.logFile.layout.type=PatternLayout
appender.logFile.layout.pattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ}: %m%n
appender.logFile.policies.type=Policies
appender.logFile.policies.time.type=TimeBasedTriggeringPolicy
appender.logFile.policies.time.interval=1
appender.logFile.policies.time.modulate=true
appender.logFile.policies.size.type=SizeBasedTriggeringPolicy
appender.logFile.policies.size.size=500MB
appender.logFile.strategy.type=DefaultRolloverStrategy
appender.logFile.strategy.max=10
appender.logFile.append=false
appender.logFile.immediateFlush=true
loggers=logFile
logger.logFile.name=Test
logger.logFile.level=debug
logger.logFile.appenderRefs=logFile
logger.logFile.appenderRef.logFile.ref=LOGFILE
logger.logFile.additivity=false
rootLogger.level=debug
rootLogger.appenderRefs=stdout
rootLogger.appenderRef.stdout.ref=STDOUT
Code:
package Test.loggingTest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
public class OneLineLog {
public static void main(String[] args) {
Logger logger = LogManager.getLogger("Test");
try {
logger.info("first writing");
LoggerContext loggerContext = (LoggerContext) LogManager.getContext();
AbstractConfiguration logConfig = (AbstractConfiguration) loggerContext.getConfiguration();
Appender logAppender = logConfig.getAppender("LOGFILE");
if (logAppender instanceof RollingFileAppender) {
RollingFileAppender rollingFileAppender = (RollingFileAppender) logAppender;
rollingFileAppender.getManager().rollover();
}
Thread.sleep(5000);
logger.info("second writing");
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
I am trying to run pig scripts remotely from my java machine, for that i have written below code
code:
import java.io.IOException;
import java.util.Properties;
import org.apache.pig.ExecType;
import org.apache.pig.PigServer;
import org.apache.pig.backend.executionengine.ExecException;
public class Javapig{
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("fs.default.name", "hdfs://hdfs://192.168.x.xxx:8022");
props.setProperty("mapred.job.tracker", "192.168.x.xxx:8021");
PigServer pigServer = new PigServer(ExecType.MAPREDUCE, props);
runIdQuery(pigServer, "fact");
}
catch(Exception e) {
System.out.println(e);
}
}
public static void runIdQuery(PigServer pigServer, String inputFile) throws IOException {
pigServer.registerQuery("A = load '" + inputFile + "' using org.apache.hive.hcatalog.pig.HCatLoader();");
pigServer.registerQuery("B = FILTER A by category == 'Aller';");
pigServer.registerQuery("DUMP B;");
System.out.println("Done");
}
}
but while executing i am getting below error.
Error
ERROR 4010: Cannot find hadoop configurations in classpath (neither hadoop-site.xml nor core-site.xml was found in the classpath).
I don't know what am i doing wrong.
Well, self describing error...
neither hadoop-site.xml nor core-site.xml was found in the classpath
You need both of those files in the classpath of your application.
You ideally would get those from your $HADOOP_CONF_DIR folder, and you would copy them into your Java's src/main/resources, assuming you have a Maven structure
Also, with those files, you should rather use a Configuration object for Hadoop
PigServer(ExecType execType, org.apache.hadoop.conf.Configuration conf)
Log4j writes to application log file instead of my own log file.
I tried to find a solution without editing the log4j.properties. Do I have to edit the config file? Why the lg file is not been created.
The app runs as a tomcat web app.
import org.apache.log4j.Logger;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.SimpleLayout;
public class ArchiveJanitor extends SecureResource {
private static final Logger logger = org.apache.log4j.Logger.getRootLogger();
public ArchiveJanitor(Context context, Request request, Response response) {
super(context, request, response);
try {
SimpleLayout layout = new SimpleLayout();
FileAppender fileAppender = new FileAppender( layout, "logs/Janitor.log", false );
logger.addAppender(fileAppender);
logger.setLevel((Level) Level.ALL);
}catch (IOException e){
logger.error(e.toString());
}
}
public void doSmth(){
logger.error("error ....")
}
}
Instead of private static final Logger logger = org.apache.log4j.Logger.getRootLogger(); try to use public static final Logger logger = LogManager.getLogger(ArchiveJanitor.class);
But probably its better to config it all in .properties file
I want to put all my config files in a /config subfolder of my application directory. Log4j is expecting the log4j.properties file in the root folder of my application. Is there a way to tell log4j where to look for the properties file?
Yes, define log4j.configuration property
java -Dlog4j.configuration=file:/path/to/log4j.properties myApp
Note, that property value must be a URL.
For more read section 'Default Initialization Procedure' in Log4j manual.
You can use PropertyConfigurator to load your log4j.properties wherever it is located in the disk.
Example:
Logger logger = Logger.getLogger(this.getClass());
String log4JPropertyFile = "C:/this/is/my/config/path/log4j.properties";
Properties p = new Properties();
try {
p.load(new FileInputStream(log4JPropertyFile));
PropertyConfigurator.configure(p);
logger.info("Wow! I'm configured!");
} catch (IOException e) {
//DAMN! I'm not....
}
If you have an XML Log4J configuration, use DOMConfigurator instead.
Use the PropertyConfigurator: PropertyConfigurator.configure(configFileUrl);
Refer to this example taken from -
http://www.dzone.com/tutorials/java/log4j/sample-log4j-properties-file-configuration-1.html
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class HelloWorld {
static final Logger logger = Logger.getLogger(HelloWorld.class);
static final String path = "src/resources/log4j.properties";
public static void main(String[] args) {
PropertyConfigurator.configure(path);
logger.debug("Sample debug message");
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");
logger.fatal("Sample fatal message");
}
}
To change the logger levels - Logger.getRootLogger().setLevel(Level.INFO);
In Eclipse you can set a VM argument to:
-Dlog4j.configuration=file:///${workspace_loc:/MyProject/log4j-full-debug.properties}
This is my class : Path is fine and properties is loaded.
package com.fiserv.dl.idp.logging;
import java.io.File;
import java.io.FileInputStream;
import java.util.MissingResourceException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class LoggingCapsule {
private static Logger logger = Logger.getLogger(LoggingCapsule.class);
public static void info(String message) {
try {
String configDir = System.getProperty("config.path");
if (configDir == null) {
throw new MissingResourceException("System property: config.path not set", "", "");
}
Properties properties = new Properties();
properties.load(new FileInputStream(configDir + File.separator + "log4j" + ".properties"));
PropertyConfigurator.configure(properties);
} catch (Exception e) {
e.printStackTrace();
}
logger.info(message);
}
public static void error(String message){
System.out.println(message);
}
}
You must use log4j.configuration property like this:
java -Dlog4j.configuration=file:/path/to/log4j.properties myApp
If the file is under the class-path (inside ./src/main/resources/ folder), you can omit the file:// protocol:
java -Dlog4j.configuration=path/to/log4j.properties myApp
I have a GWT project running in dev and production mode as well as on web and mobile.
I have different web.xml files for each mode.
I also need different constants for each version. Currently I use this:
class Params {
public static final String SOME_CONSTANT = "value";
...
}
The value of SOME_CONSTANT may change across modes (versions of the app).
How can I have different constants for each mode (dev, prod, web, mobile)?
Move these constants into properties file one for each environment.
create a folder like this (It must be outside of your final generated war file, somewhere on server)
resources
|__dev
|__prod
|__web
|__mobile
Each folder contains properties file having values based on environment.
Pass the value of environment at start up of server as system property or environment variable. Load all the properties at the application context initialization and use it anywhere in your application.
Use ServletContextListener to read all the properties at server start up.
How to load properties file based on system properties or environment variable?
Use
System.getProperty()
or
System.getenv()
to read the location of properties file.
and load the properties file
Properties properties = new Properties()
properties.load(new FileInputStream(new File(absolutePath)));
You can store properties as Application context attribute that can be read from anywhere including JSP as well.
--EDIT--
Load properties file at server start-up:
web.xml
<listener>
<listener-class>com.x.y.z.server.AppServletContextListener</listener-class>
</listener>
AppServletContextListener.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AppServletContextListener implements ServletContextListener {
private static Properties properties = new Properties();
static {
// load properties file
String absolutePath = null;
if (System.getenv("properties_absolute_path") == null) {
absolutePath = System.getProperty("properties_absolute_path");
} else {
absolutePath = System.getenv("properties_absolute_path");
}
try {
File file = new File(absolutePath);
properties.load(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
servletContextEvent.getServletContext().setAttribute("properties", properties);
}
public static Properties getProperties() {
return properties;
}
}