0

I am using the following code to create a custom log as per my requirements.

But unable to get the rollback feature as java.util.logging.Logger doesn't support it.

What are the possible options for me to implement?

Is it possible to generate rollback logs automatically using the same library?

Code :

private static class MyCustomFormatterforUpdate extends java.util.logging.Formatter {

    @Override
    public String format(LogRecord record) {
        StringBuffer sb = new StringBuffer();
        sb.append("update ApiStatistics set RespDateTime =");
        sb.append(record.getMessage());
        sb.append(";");
        sb.append("\n");
        return sb.toString();
    }

}

java.util.logging.Logger updatefile = java.util.logging.Logger.getLogger("Update Script");
boolean appendu = false;
FileHandler fhu;

{
    try {
        fhu = new FileHandler("src/main/resources/updatescript.log",appendu);
        updatefile.addHandler(fhu);
        fhu.setFormatter(new MyCustomFormatterforUpdate());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Sri
  • 437
  • 1
  • 4
  • 13
  • Does [this](https://stackoverflow.com/questions/30985882/java-util-logger-new-file-every-day) answer your question? – JustAnotherDeveloper Aug 21 '20 at 11:28
  • No, As it only partially answers the question.I am looking for a solution that does it on daily basis. The above solution is on each call. – Yogesh Mallik Aug 21 '20 at 11:32
  • Further answers say that the logging utility you're using does not support that feature, however. I'm afraid you're going to have to switch to a different one. Or maybe the last answer in that question will work, as it relies on a task that runs daily. – JustAnotherDeveloper Aug 21 '20 at 11:37
  • What are the possible libraries I can use which support custom formatter and File handler? – Yogesh Mallik Aug 21 '20 at 11:39

2 Answers2

1

A suggestion would be please use other logging frameworks which has many features in them instead of java.util.logging.Logger

Useful links

  1. configure-log4j-for-creating-daily-rolling-log-files
  2. log4j-formatting-examples
  3. a-guide-to-logging-in-java
Sri
  • 437
  • 1
  • 4
  • 13
1

Building upon my previous answer you just need to build out the proxy implementation inferred in that answer. The idea is to install a proxy handler which allows you to open and close the FileHandler object. This enabled the rotation you need. Below is working example that will rotate when the date changes. The test case is included and the output will appear in the home folder by default.

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Calendar;
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.SimpleFormatter;
import java.util.logging.XMLFormatter;

public class DailyFileHandler extends Handler {
    
    public static void main(String[] args) throws IOException {
        DailyFileHandler dfh = new DailyFileHandler();
        try {
            dfh.setFormatter(new SimpleFormatter());
            LogRecord r1 = new LogRecord(Level.SEVERE, "test 1");
            LogRecord r2 = new LogRecord(Level.SEVERE, "test 2");
            r2.setMillis(r1.getMillis() + (24L * 60L * 60L * 1000L));
            dfh.publish(r1);
            dfh.publish(r2);
            
        } finally {
            dfh.close();
        }
    }
    
    private Calendar current = Calendar.getInstance();
    private FileHandler target;
    
    public DailyFileHandler() throws IOException {
        target = new FileHandler(pattern(), limit(), count(), false);
        init();
    }
    
    public DailyFileHandler(String pattern, int limit, int count)
            throws IOException {
        target = new FileHandler(pattern, limit, count, false);
        init();
    }
    
    private void init() {
        super.setLevel(level());
        super.setFormatter(formatter());
        super.setFilter(filter());
        try {
            super.setEncoding(encoding());
        } catch (UnsupportedEncodingException impossible) {
            throw new AssertionError(impossible);
        }
        initTarget();
    }
    
    private void initTarget() {
        target.setErrorManager(super.getErrorManager());
        target.setLevel(super.getLevel());
        target.setFormatter(super.getFormatter());
        target.setFilter(super.getFilter());
        try {
            target.setEncoding(super.getEncoding());
        } catch (UnsupportedEncodingException impossible) {
            throw new AssertionError(impossible);
        }
    }
    
    private void rotate() {
        String pattern = pattern();
        int count = count();
        int limit = limit();
        try {
            super.setErrorManager(target.getErrorManager());
            target.close();
            
            FileHandler rotate = new FileHandler(pattern, 0, count, false);
            rotate.setFormatter(new SimpleFormatter()); //empty tail.
            rotate.close();
            
            current = Calendar.getInstance();
            target = new FileHandler(pattern, limit, count, true);
            initTarget();
        } catch (RuntimeException | IOException e) {
            this.reportError("", e, ErrorManager.OPEN_FAILURE);
        }
    }
    
    private boolean shouldRotate(long millis) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(millis);
        return cal.get(Calendar.DAY_OF_YEAR) != current.get(Calendar.DAY_OF_YEAR);
    }

    @Override
    public synchronized void publish(LogRecord record) {
        if (shouldRotate(record.getMillis())) {
            rotate();
        }
        target.publish(record);
    }

    @Override
    public synchronized void close() throws SecurityException {
        target.close();
    }

    @Override
    public synchronized void setEncoding(String encoding) throws SecurityException, UnsupportedEncodingException {
        target.setEncoding(encoding);
        super.setEncoding(encoding);
    }

    @Override
    public synchronized boolean isLoggable(LogRecord record) {
        return target.isLoggable(record);
    }

    @Override
    public synchronized void flush() {
        target.flush();
    }

    @Override
    public synchronized void setFormatter(Formatter newFormatter) {
        target.setFormatter(newFormatter);
        super.setFormatter(newFormatter);
    }

    @Override
    public synchronized Formatter getFormatter() {
        return target.getFormatter();
    }

    @Override
    public synchronized String getEncoding() {
        return target.getEncoding();
    }

    @Override
    public synchronized void setFilter(Filter newFilter) throws SecurityException {
        target.setFilter(newFilter);
        super.setFilter(newFilter);
    }

    @Override
    public synchronized Filter getFilter() {
        return target.getFilter();
    }

    @Override
    public synchronized void setErrorManager(ErrorManager em) {
        target.setErrorManager(em);
        super.setErrorManager(em);
    }

    @Override
    public synchronized ErrorManager getErrorManager() {
        return target.getErrorManager();
    }

    @Override
    public synchronized void setLevel(Level newLevel) throws SecurityException {
        target.setLevel(newLevel);
        super.setLevel(newLevel);
    }

    @Override
    public synchronized Level getLevel() {
        return target.getLevel();
    }

    private String pattern() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String pattern = m.getProperty(p + ".pattern");
        if (pattern == null) {
            pattern = "%h/java%u.log";
        }
        return pattern;
    }
    
    private int limit() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".limit");
        int limit = v == null ? Integer.MAX_VALUE : Integer.parseInt(v);
        return limit;
    }
    
    private int count() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".count");
        int limit = v == null ? 7 : Integer.parseInt(v);
        return limit;
    }
    
    private Level level() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".level");
        if (v != null) {
            try {
                return Level.parse(v);
            } catch (Exception e) {
                this.reportError(v, e, ErrorManager.OPEN_FAILURE);
            }
        }
        return Level.ALL;
    }
    
    private Formatter formatter() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".formatter");
        if (v != null) {
            try {
                return Formatter.class.cast(Class.forName(v).newInstance());
            } catch (Exception e) {
                this.reportError("", e, ErrorManager.OPEN_FAILURE);
            }
        }
        return new XMLFormatter();
    }
    
    private Filter filter() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".filter");
        if (v != null) {
            try {
                return Filter.class.cast(Class.forName(v).newInstance());
            } catch (Exception e) {
                this.reportError("", e, ErrorManager.OPEN_FAILURE);
            }
        }
        return null;
    }
    
    private String encoding() {
        LogManager m = LogManager.getLogManager();
        String p = getClass().getName();
        String v = m.getProperty(p + ".encoding");
        if (v != null) {
            try {
                return Charset.forName(v).name();
            } catch (Exception e) {
                this.reportError(v, e, ErrorManager.OPEN_FAILURE);
            }
        }
        return null;
    }
}
jmehrens
  • 10,580
  • 1
  • 38
  • 47