All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.logging.WatchedFileHandler Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.logging;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.logging.ErrorManager;
import java.util.logging.FileHandler;
import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.XMLFormatter;

/**
 * File handler that watches the file it is logging to. If the file changes, it gets closed and reopened with the same
 * filename.
 * 

* This handler is useful for when log rotation is to be handled outside of the standard Java Logging system, for * example with a program like logrotate. Without the watch-functionality it would keep writing to the old (rotated) * file. */ public class WatchedFileHandler extends Handler { private Path watchedFile; private FileHandler wrappedHandler; private Thread fileWatcher; public WatchedFileHandler() throws IOException { String filename = getProperty("filename", "yamcs.log"); watchedFile = Paths.get(filename); wrappedHandler = new FileHandler(filename, true /* append */); setLevel(getLevelProperty("level", Level.ALL)); setFilter(getFilterProperty("filter", null)); setFormatter(getFormatterProperty("formatter", new XMLFormatter())); try { setEncoding(getProperty("encoding", null)); } catch (SecurityException | UnsupportedEncodingException e) { // Ignore } fileWatcher = new FileWatcher(); fileWatcher.start(); } private synchronized void reopenFile() { Level oldLevel = getLevel(); Filter oldFilter = getFilter(); Formatter oldFormatter = getFormatter(); String oldEncoding = getEncoding(); setLevel(Level.OFF); wrappedHandler.close(); try { wrappedHandler = new FileHandler(watchedFile.toString(), true); } catch (IOException e) { // Avoid throwing reportError(null, e, ErrorManager.OPEN_FAILURE); } setFilter(oldFilter); setFormatter(oldFormatter); try { setEncoding(oldEncoding); } catch (SecurityException | UnsupportedEncodingException e) { // Ignore } setLevel(oldLevel); } @Override public synchronized void publish(LogRecord record) { wrappedHandler.publish(record); } @Override public synchronized void flush() { wrappedHandler.flush(); } @Override public synchronized void close() throws SecurityException { fileWatcher.interrupt(); wrappedHandler.close(); } @Override public synchronized void setEncoding(String encoding) throws SecurityException, UnsupportedEncodingException { wrappedHandler.setEncoding(encoding); } @Override public synchronized void setFormatter(Formatter newFormatter) throws SecurityException { wrappedHandler.setFormatter(newFormatter); } @Override public synchronized void setErrorManager(ErrorManager em) { wrappedHandler.setErrorManager(em); } @Override public synchronized void setFilter(Filter newFilter) throws SecurityException { wrappedHandler.setFilter(newFilter); } @Override public synchronized void setLevel(Level newLevel) throws SecurityException { wrappedHandler.setLevel(newLevel); } @Override public boolean isLoggable(LogRecord record) { return wrappedHandler.isLoggable(record); } @Override public String getEncoding() { return wrappedHandler.getEncoding(); } @Override public ErrorManager getErrorManager() { return wrappedHandler.getErrorManager(); } @Override public Filter getFilter() { return wrappedHandler.getFilter(); } @Override public Level getLevel() { return wrappedHandler.getLevel(); } @Override public Formatter getFormatter() { return wrappedHandler.getFormatter(); } private Level getLevelProperty(String name, Level defaultValue) { String val = getProperty(name, null); if (val == null) { return defaultValue; } Level l = Level.parse(val.trim()); return l != null ? l : defaultValue; } private Filter getFilterProperty(String name, Filter defaultValue) { String val = getProperty(name, null); try { if (val != null) { Class clz = ClassLoader.getSystemClassLoader().loadClass(val); return (Filter) clz.getDeclaredConstructor().newInstance(); } } catch (Exception e) { // Ignore } return defaultValue; } private Formatter getFormatterProperty(String name, Formatter defaultValue) { String val = getProperty(name, null); try { if (val != null) { Class clz = ClassLoader.getSystemClassLoader().loadClass(val); return (Formatter) clz.getDeclaredConstructor().newInstance(); } } catch (Exception e) { // Ignore } return defaultValue; } private String getProperty(String name, String defaultValue) { LogManager manager = LogManager.getLogManager(); String qname = getClass().getName() + "." + name; String property = manager.getProperty(qname); return property != null ? property : defaultValue; } private class FileWatcher extends Thread { @Override public void run() { Path parent = watchedFile.getParent(); try (WatchService watchService = FileSystems.getDefault().newWatchService()) { parent.register(watchService, StandardWatchEventKinds.ENTRY_DELETE); while (true) { WatchKey key = watchService.take(); for (WatchEvent event : key.pollEvents()) { Path relpath = (Path) event.context(); if (parent.resolve(relpath).equals(watchedFile)) { reopenFile(); } } key.reset(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (IOException e) { throw new UncheckedIOException(e); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy