LoveMeow
LoveMeow

Reputation: 4038

How to reduce the frequency of logging in Java?

I am using java logging(the one provided by default)in the java environment.

I wanted to ask how I could aggregate my readings and log lets say once every second instead of more often(I seem to be logging 20 times a second). How can that be done?

Is there any setting that I can use where it pushes data to file less often? I have never logged before so I am not sure if it is possible.Thank you.

EDIT: I am logging response time, throughput and stuff like that. Since my program is heavy I want jul to buffer and log less often.

Upvotes: 0

Views: 890

Answers (1)

Marcin Król
Marcin Król

Reputation: 1654

To customize logging with JUL you can write your own Handler implementation. If you want to log to a file you should extend FileHandler. An implementation using ConsoleHandler could look like this:

package my.logging;

import java.util.Queue;
import java.util.concurrent.*;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogRecord;

public class BufferingHandler extends ConsoleHandler implements AutoCloseable {

    private final Queue<LogRecord> logRecordsFifo = new ConcurrentLinkedQueue<>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public BufferingHandler(final int delay, final TimeUnit timeUnit) {
        super();
        scheduler.scheduleWithFixedDelay(() -> handleLogs(), delay, delay, timeUnit);
    }

    private void handleLogs() {
        while (!logRecordsFifo.isEmpty()) {
            // sync is required to preserve logs order when flushing
            synchronized (logRecordsFifo) { 
                final LogRecord log = logRecordsFifo.poll();
                if (log != null) super.publish(log);
            }
        }
    }

    @Override
    public void publish(final LogRecord record) {
        if (!isLoggable(record)) return;
        logRecordsFifo.add(record);
    }

    @Override
    public void flush() {
        handleLogs();
        super.flush();
    }

    @Override
    public void close() {
        scheduler.shutdown();
        flush();
        super.close();
    }
}

Usage of this handler could look like this:

import my.logging.BufferingHandler;

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class App {

    public static void main(String[] args) throws InterruptedException {
        final Logger logger = Logger.getLogger(App.class.getName());
        try (final BufferingHandler bufferingHandler = new BufferingHandler(1, TimeUnit.SECONDS)) {
            logger.addHandler(bufferingHandler);
            for (int i = 0; i < 30; ++i) {
                Thread.sleep(200);
                logger.info("some info: " + i);
            }
        }
    }

}

Upvotes: 2

Related Questions