Skip to content

Commit

Permalink
Refactor Logging Support
Browse files Browse the repository at this point in the history
- Change to FileLogger and register static references
  • Loading branch information
Phillipus committed Jul 31, 2023
1 parent 9912358 commit 82df76a
Showing 1 changed file with 71 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
import java.net.URL;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
Expand All @@ -22,28 +25,55 @@
import org.eclipse.ui.PlatformUI;

/**
* Logging Support
* File Logging Support
*
* Uses java.util.logging to log to a localised file for a given plug-in.
*
* <p>Example Usage:<p>
<pre>
LoggingSupport loggingSupport = new LoggingSupport("com.archimatetool.myplugin",
getBundle().getEntry("logging.properties"),
new File(getLoggingFolder(), "log-%g.txt"));
loggingSupport.start();
// Use the logger...
loggingSupport.stop();
FileLogger.create("com.archimatetool.myplugin",
getBundle().getEntry("logging.properties"),
new File(getLoggingFolder(), "log-%g.txt"));
</pre>
*
* @author Phillip Beauvoir
*/
@SuppressWarnings("nls")
public class LoggingSupport {
public class FileLogger {

private static final int MAX_BYTES = 1024 * 1024 * 10; // 10 mb files
private static final int FILE_COUNT = 3; // Max files to use

/**
* Registered loggers
*/
private static Map<String, FileLogger> loggers = new HashMap<>();

/**
* Create and start Java Logging to file
*
* @param rootPackageName root package name that will be used for the root logger
* @param propertiesFile bundle location of logging.properties file (can be null)
* @param fileNamePattern absolute file name pattern of the logging file to write to
*/
public static FileLogger create(String rootPackageName, URL propertiesFile, File fileNamePattern) throws SecurityException, IOException {
FileLogger logger = loggers.get(rootPackageName);

if(logger == null) {
logger = new FileLogger(rootPackageName, propertiesFile, fileNamePattern);
loggers.put(rootPackageName, logger);
}

return logger;
}

/**
* Return a previsously created FileLogger, or null if it hasn't been created yet or has been closed
*/
public static FileLogger get(String rootPackageName) {
return loggers.get(rootPackageName);
}

/**
* Use our own extension of SimpleFormatter because we don't want to set a global, singleton format
* with property "java.util.logging.SimpleFormatter.format" as this will be global and will set it for other SimpleFormatter usages.
Expand Down Expand Up @@ -101,57 +131,39 @@ public String format(LogRecord record) {
}

private String rootPackageName;
private URL propertiesFile;
private File fileNamePattern;

private Logger rootLogger;
private FileHandler fileHandler;

/**
* @param rootPackageName root package name that will be used for the root logger
* @param propertiesFile bundle location of logging.properties file (can be null)
* @param fileNamePattern absolute file name pattern of the logging file
*/
public LoggingSupport(String rootPackageName, URL propertiesFile, File fileNamePattern) {
private FileLogger() {
}

private FileLogger(String rootPackageName, URL propertiesFile, File fileNamePattern) throws SecurityException, IOException {
this.rootPackageName = rootPackageName;
this.propertiesFile = propertiesFile;
this.fileNamePattern = fileNamePattern;

// The root logger is the root class package name of the bundle
// The root logger is the root class package name of the plug-in
rootLogger = Logger.getLogger(rootPackageName);

// Don't use parent handlers so there's no logging to console
rootLogger.setUseParentHandlers(false);
}

/**
* Get a Logger for its name
* We use this proxy method rather than the direct call to ensure that the root logger is initialised
*/
public Logger getLogger(String name) {
return Logger.getLogger(name);
}

/**
* Initialise the file handler for logging to file
*/
public void start() throws SecurityException, IOException {
// Don't use file logging if running headless (unit tests)
if(!PlatformUI.isWorkbenchRunning()) {
return;
}

// Read logging properties file, if any
if(propertiesFile != null) {
try(InputStream is = propertiesFile.openStream()) {
LogManager.getLogManager().updateConfiguration(is, null);
}
}

// Don't use file logging if running headless (unit tests)
if(!PlatformUI.isWorkbenchRunning()) {
return;
}

// Parent folder must exist for logging file and lock file
fileNamePattern.getParentFile().mkdirs();
if(fileNamePattern.getParentFile() != null) {
fileNamePattern.getParentFile().mkdirs();
}

// Set file handler on root logger
// Set file handler and format on the root logger
fileHandler = new FileHandler(fileNamePattern.getAbsolutePath(), MAX_BYTES, FILE_COUNT, true); // 10mb
String format = LogManager.getLogManager().getProperty(rootPackageName + ".format");
fileHandler.setFormatter(new ExtSimpleFormatter(format));
Expand All @@ -160,12 +172,28 @@ public void start() throws SecurityException, IOException {
}

/**
* Close the file handler
* Set the root logger to level
*/
public void setLevel(Level newLevel) {
if(rootLogger != null) {
rootLogger.setLevel(newLevel);
}
}

/**
* Close the logger and stop logging. The logger will be unregistered and calls to get(packagename) will return null.
*/
public void stop() {
public void close() {
if(fileHandler != null) {
fileHandler.close();
fileHandler = null;
}

if(rootLogger != null) {
rootLogger.removeHandler(fileHandler);
}

fileHandler = null;
rootLogger = null;
loggers.remove(rootPackageName);
}
}

0 comments on commit 82df76a

Please sign in to comment.