Skip to content
Permalink
Browse files

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
  • Loading branch information...
luccioman committed Sep 13, 2018
1 parent 7adbd1f commit db7ad7636605f9051bb7ef07bad6964cecddb163
Showing with 52 additions and 40 deletions.
  1. +44 −33 source/net/yacy/cora/util/ConcurrentLog.java
  2. +8 −7 source/net/yacy/yacy.java
@@ -20,6 +20,7 @@

package net.yacy.cora.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -29,9 +30,9 @@
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
@@ -378,46 +379,58 @@ public void run() {
}
}

public final static void configureLogging(final File dataPath, final File appPath, final File loggingConfigFile) throws SecurityException, FileNotFoundException, IOException {
FileInputStream fileIn = null;
try {
System.out.println("STARTUP: Trying to load logging configuration from file " + loggingConfigFile.toString());
fileIn = new FileInputStream(loggingConfigFile);

// loading the logger configuration from file
final LogManager logManager = LogManager.getLogManager();
logManager.readConfiguration(fileIn);

// creating the logging directory
String logPattern = logManager.getProperty("java.util.logging.FileHandler.pattern");
File logFile = new File(logPattern);
if (!logFile.isAbsolute()) {
logFile = new File(dataPath, logPattern);
logPattern = logFile.getAbsolutePath();
public static final void configureLogging(final File dataPath, final File loggingConfigFile) throws SecurityException, FileNotFoundException, IOException {
System.out.println("STARTUP: Trying to load logging configuration from file " + loggingConfigFile.toString());
try (final FileInputStream fileIn = new FileInputStream(loggingConfigFile);){

final String logFilePatternKey = "java.util.logging.FileHandler.pattern";
final Properties logProperties = new Properties();
logProperties.load(fileIn);
String logFilePattern = logProperties.getProperty(logFilePatternKey, "%h/java%u.log" /* default FileHandler pattern*/);

File logFile;
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()) {
logFile = new File(dataPath, logFilePattern);
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();
if(logDirectory != null) {
if (!logDirectory.isAbsolute()) {
logDirectory = new File(dataPath, logDirectory.getPath());
}
if (!logDirectory.exists()) {
if(!logDirectory.mkdir()) {
if(!logDirectory.mkdirs()) {
System.err.println("STARTUP: Could not create the logs directory at " + logDirectory.getAbsolutePath());
}
} else if(!logDirectory.isDirectory()) {
System.err.println("STARTUP: Log file parent path at " + logDirectory.getAbsolutePath() + "is not a directory");
}
}

// generating the root logger
final Logger logger = Logger.getLogger("");
logger.setUseParentHandlers(false);

//for (Handler h: logger.getHandlers()) logger.removeHandler(h);
if (!dataPath.getAbsolutePath().equals(appPath.getAbsolutePath())) {
final FileHandler handler = new FileHandler(logPattern, 1024*1024, 20, true);
logger.addHandler(handler);
}

final ByteArrayOutputStream propsStream = new ByteArrayOutputStream();
logProperties.store(propsStream, null);

// loading the logger configuration from properties
final LogManager logManager = LogManager.getLogManager();
logManager.readConfiguration(new ByteArrayInputStream(propsStream.toByteArray()));

// redirect uncaught exceptions to logging
final ConcurrentLog exceptionLog = new ConcurrentLog("UNCAUGHT-EXCEPTION");
@@ -438,8 +451,6 @@ public void uncaughtException(final Thread t, final Throwable e) {
}
}
});
} finally {
if (fileIn != null) try {fileIn.close();}catch(final Exception e){}
}
}

@@ -166,6 +166,13 @@ private static void startup(final File dataHome, final File appHome, final long
System.err.println("Error creating DATA-directory in " + dataHome.toString() + " . Please check your write-permission for this folder. YaCy will now terminate.");
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
f = new File(dataHome, "DATA/LOG/");
@@ -178,7 +185,7 @@ private static void startup(final File dataHome, final File appHome, final long
System.out.println("could not copy yacy.logging");
}
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) {
System.out.println("could not find logging properties in homePath=" + dataHome);
ConcurrentLog.logException(e);
@@ -203,12 +210,6 @@ private static void startup(final File dataHome, final File appHome, final long
lock = channel.tryLock(); // lock yacy.running
} 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 {
sb = new Switchboard(dataHome, appHome, "defaults/yacy.init".replace("/", File.separator), conf);
} catch (final RuntimeException e) {

0 comments on commit db7ad76

Please sign in to comment.
You can’t perform that action at this time.