I am working on an application that will run on OSX and windows. I want the logs to be written to the users home directory. For OSX it will be under the /Users//Library/Application Support/MyApp/log directory, and under windows depending on the version under /Users//AppData/MyApp/log directory.
What is the best way I can do this? I have looked around for solutions for this, but nothing helpful or a solution I am comfortable using has come up.
Look forward to your inputs.
edit:
Since the location of the log file depends on the OS, I am hoping to find a run time solution, possibly something like below
if (System.getProperty("os.name").contains("mac"))
logFileLocation = System.getProperty("user.home") + "/Library/Application Support/MyApp/logs"
else
logFileLocation = System.getenv("APPDATA") + "/MyApp/logs"
Thanks
Change the ConsoleAppender
to a FileAppender
. As far as I know the write request will be redirected to appdata on windows OS. Not sure about MacOs.
URL mySource = MyAppMainClass.class.getProtectionDomain().getCodeSource().getLocation();
File rootFolder = new File(mySource.getPath());
System.setProperty("app.root", rootFolder.getAbsolutePath());
and edit log4j config like this
log4j.appender.NotConsole=org.apache.log4j.RollingFileAppender
log4j.appender.NotConsole.fileName=${app.root}/fileName.log
or for user home:
log4j.appender.NotConsole.fileName=${user.home}/fileName.log
Thank you all for the inputs. based on the hint that Alex proposed I went with the following approach,
In log4j.properties I had the following configuration
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=${userApp.root}/logs/myapp.log
and at the start of the application I have done this.
System.setProperty("userApp.root", getUserAppDirectory());
the getUserAppDirectory() method is defined as
static String getUserAppDirectory() {
if (isMacOS())
return System.getProperty("user.home") + "/Library/Application Support/myapp";
else
return System.getenv("APPDATA") + "/myapp";
}
Possibly the cleanest approach would be to write your log4j configuration assuming a particular system property (say myapp.data.dir
)
log4j.appender.logfile.fileName=${myapp.data.dir}/logs/myapp.log
and set that property in the appropriate way in the launcher for each platform. For example if you're using an .app
bundle on Mac OS X then you can set system properties in Info.plist
<plist version="1.0">
<dict>
<!-- ... -->
<key>Java</key>
<dict>
<!-- ... -->
<key>Properties</key>
<dict>
<key>apple.laf.useScreenMenuBar</key>
<string>true</string>
<key>myapp.data.dir</key>
<string>$USER_HOME/Library/Application Support/MyApp</string>
or set it relative to the APPDATA environment variable on Windows (which would handle the difference between XP and 7). With a Launch4J .exe
you could put -Dmyapp.data.dir="%APPDATA%\MyApp"
in the .l4j.ini
file.
You'd need explicit code to initialize log4j before you try and access any loggers
if(System.getProperty("myapp.data.dir") == null) {
// fallback to ~/.myapp (sensible Linux default) if run without a launcher
System.setProperty("myapp.data.dir", new File(
System.getProperty("user.home"), ".myapp").getAbsolutePath());
}
// ensure log directory exists
new File(new File(System.getProperty("myapp.data.dir")), "logs").mkdirs();
// now it's safe to configure log4j
PropertyConfigurator.configure(this.getClass().getResource("/log4j.properties"));
I have Solved path issue of log4j.xml in mac :
in windows we configure log4j in web.xml like :
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>file:${LOG4J_HOME}/conf/log4j.xml</param-value>
<!-- Above path is that where we have stored log4j.xml file externally -->
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param>
Where ${LOG4J_HOME} is user varible we use to set in window. like
user variable = LOG4J_HOME
value = D:/LOG4J (in d drive we have created a folder of name Log4J we copied that path and gave as a value)
In mac we have envirenvirent variable set fasility by bash command, but it didint work anymore.
so for mac we have to create one folder any where and we have to give static path of that folder.
like in xml :
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>file:/Users/vardhaman/Desktop/LOG4J/conf/log4j.xml</param-value>
<!-- Above path is that where we have stored log4j.xml file externally to get this path go up to the log4j.xml file in external device and right click select get info, where we will get path, copy that path -->
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param>
Same way we have to do in log4j.xml file
In window we use to do like :
<appender name="CLICK-SPRING" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${LOG4J_HOME}/logs/CLICK/CLICK-spring.log"/>
<param name="Append" value="true"/>
<param name="Threshold" value="DEBUG"/>
<param name="MaxFileSize" value="100MB"/>
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p [%t] %C{1}.%M(%L) | %m%n"/>
</layout>
</appender>
In mac :
in place of value we have to copy static path up to folder LOG4J, or you can create any folder.
<appender name="CLICK-SPRING" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="Users/vardhaman/Desktop/LOG4J/logs/CLICK/CLICK-spring.log"/>
<param name="Append" value="true"/>
<param name="Threshold" value="DEBUG"/>
<param name="MaxFileSize" value="100MB"/>
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p [%t] %C{1}.%M(%L) | %m%n"/>
</layout>
</appender>