Improved support for Java logs file pattern options

- support of "%h" and "%t" pattern components
- more proper initialization of file handler when the data folder is not
the default one, notably to prevent a non blocking but ugly error stack
trace reported by the log manager at startup with that kind of setup
pull/240/head
luccioman 7 years ago
parent 7adbd1f87d
commit db7ad76366

@ -20,6 +20,7 @@
package net.yacy.cora.util; package net.yacy.cora.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -29,9 +30,9 @@ import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.logging.FileHandler;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.LogManager; import java.util.logging.LogManager;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -378,30 +379,45 @@ public final class ConcurrentLog {
} }
} }
public final static void configureLogging(final File dataPath, final File appPath, final File loggingConfigFile) throws SecurityException, FileNotFoundException, IOException { public static final void configureLogging(final File dataPath, final File loggingConfigFile) throws SecurityException, FileNotFoundException, IOException {
FileInputStream fileIn = null;
try {
System.out.println("STARTUP: Trying to load logging configuration from file " + loggingConfigFile.toString()); System.out.println("STARTUP: Trying to load logging configuration from file " + loggingConfigFile.toString());
fileIn = new FileInputStream(loggingConfigFile); try (final FileInputStream fileIn = new FileInputStream(loggingConfigFile);){
// loading the logger configuration from file final String logFilePatternKey = "java.util.logging.FileHandler.pattern";
final LogManager logManager = LogManager.getLogManager(); final Properties logProperties = new Properties();
logManager.readConfiguration(fileIn); logProperties.load(fileIn);
String logFilePattern = logProperties.getProperty(logFilePatternKey, "%h/java%u.log" /* default FileHandler pattern*/);
// creating the logging directory
String logPattern = logManager.getProperty("java.util.logging.FileHandler.pattern"); File logFile;
File logFile = new File(logPattern); if(logFilePattern.startsWith("%h")) {
logFile = new File(System.getProperty("user.home") + logFilePattern.substring(2));
} else if(logFilePattern.startsWith("%t")) {
String tmpDir = System.getProperty("java.io.tmpdir");
if (tmpDir == null) {
tmpDir = System.getProperty("user.home");
}
logFile = new File(tmpDir, logFilePattern.substring(2));
} else {
logFile = new File(logFilePattern);
if (!logFile.isAbsolute()) { if (!logFile.isAbsolute()) {
logFile = new File(dataPath, logPattern); logFile = new File(dataPath, logFilePattern);
logPattern = logFile.getAbsolutePath(); logFilePattern = logFile.getAbsolutePath();
/*
* Update the file pattern with the absolute path flavor as LogManager and
* FileHandler classes do not offer a way to configure the base parent path when
* using relative path
*/
logProperties.setProperty(logFilePatternKey, logFilePattern);
}
} }
// creating the logging directory if necessary
File logDirectory = logFile.getParentFile(); File logDirectory = logFile.getParentFile();
if(logDirectory != null) { if(logDirectory != null) {
if (!logDirectory.isAbsolute()) {
logDirectory = new File(dataPath, logDirectory.getPath());
}
if (!logDirectory.exists()) { if (!logDirectory.exists()) {
if(!logDirectory.mkdir()) { if(!logDirectory.mkdirs()) {
System.err.println("STARTUP: Could not create the logs directory at " + logDirectory.getAbsolutePath()); System.err.println("STARTUP: Could not create the logs directory at " + logDirectory.getAbsolutePath());
} }
} else if(!logDirectory.isDirectory()) { } else if(!logDirectory.isDirectory()) {
@ -409,15 +425,12 @@ public final class ConcurrentLog {
} }
} }
// generating the root logger final ByteArrayOutputStream propsStream = new ByteArrayOutputStream();
final Logger logger = Logger.getLogger(""); logProperties.store(propsStream, null);
logger.setUseParentHandlers(false);
//for (Handler h: logger.getHandlers()) logger.removeHandler(h); // loading the logger configuration from properties
if (!dataPath.getAbsolutePath().equals(appPath.getAbsolutePath())) { final LogManager logManager = LogManager.getLogManager();
final FileHandler handler = new FileHandler(logPattern, 1024*1024, 20, true); logManager.readConfiguration(new ByteArrayInputStream(propsStream.toByteArray()));
logger.addHandler(handler);
}
// redirect uncaught exceptions to logging // redirect uncaught exceptions to logging
final ConcurrentLog exceptionLog = new ConcurrentLog("UNCAUGHT-EXCEPTION"); final ConcurrentLog exceptionLog = new ConcurrentLog("UNCAUGHT-EXCEPTION");
@ -438,8 +451,6 @@ public final class ConcurrentLog {
} }
} }
}); });
} finally {
if (fileIn != null) try {fileIn.close();}catch(final Exception e){}
} }
} }

@ -167,6 +167,13 @@ public final class yacy {
System.exit(-1); System.exit(-1);
} }
// set jvm tmpdir to a subdir for easy cleanup (as extensive use file.deleteonexit waists memory during long runs, as todelete files names are collected and never cleaned up during runtime)
// keep this as earlier as possible, as any other class can use the "java.io.tmpdir" property, even the log manager, when the log file pattern uses "%t" as an alias for the tmp directory
try {
tmpdir = java.nio.file.Files.createTempDirectory("yacy-tmp-").toString(); // creates sub dir in jvm's temp (see System.property "java.io.tempdir")
System.setProperty("java.io.tmpdir", tmpdir);
} catch (IOException ex) { }
// setting up logging // setting up logging
f = new File(dataHome, "DATA/LOG/"); f = new File(dataHome, "DATA/LOG/");
mkdirsIfNeseccary(f); mkdirsIfNeseccary(f);
@ -178,7 +185,7 @@ public final class yacy {
System.out.println("could not copy yacy.logging"); System.out.println("could not copy yacy.logging");
} }
try{ try{
ConcurrentLog.configureLogging(dataHome, appHome, new File(dataHome, "DATA/LOG/yacy.logging")); ConcurrentLog.configureLogging(dataHome, new File(dataHome, "DATA/LOG/yacy.logging"));
} catch (final IOException e) { } catch (final IOException e) {
System.out.println("could not find logging properties in homePath=" + dataHome); System.out.println("could not find logging properties in homePath=" + dataHome);
ConcurrentLog.logException(e); ConcurrentLog.logException(e);
@ -203,12 +210,6 @@ public final class yacy {
lock = channel.tryLock(); // lock yacy.running lock = channel.tryLock(); // lock yacy.running
} catch (final Exception e) { } } catch (final Exception e) { }
// set jvm tmpdir to a subdir for easy cleanup (as extensive use file.deleteonexit waists memory during long runs, as todelete files names are collected and never cleaned up during runtime)
try {
tmpdir = java.nio.file.Files.createTempDirectory("yacy-tmp-").toString(); // creates sub dir in jvm's temp (see System.property "java.io.tempdir")
System.setProperty("java.io.tmpdir", tmpdir);
} catch (IOException ex) { }
try { try {
sb = new Switchboard(dataHome, appHome, "defaults/yacy.init".replace("/", File.separator), conf); sb = new Switchboard(dataHome, appHome, "defaults/yacy.init".replace("/", File.separator), conf);
} catch (final RuntimeException e) { } catch (final RuntimeException e) {

Loading…
Cancel
Save