Search code examples
javacsvloggingfilehandlerlog-rotation

Java rotating logs with constant header


I made some system and now I want to keep track of some statistics about it while it is running. I decided to use TSV form to write down those statistics. While looking for best existing lib (if I could, I'd like to avoid implementing it on my own) I found that FileHandler lib is almost exactly what I want.

Since the statistics will be gathered every second, I suppose I need some kind of log files rotation on size limit, which File handler offers, BUT what I still miss and what is important to me is the ability to have constant header in all log files.

So I'd like to have custom first line in all log files rotated (containing meaning of the columns in TSV format) and the rest of the lines would be real statistic numbers.

Does anyone have any idea how to accomplish this? I was unable to find lib suiting me or other similar questions.

Also, if you know some other lib which could acomplish this, I'd be willing to ditch FileHandler in favor of that one.

Thanks in advance!

EDIT: So based on the answer provided by @jmehrens i made following code and it works like charm! Here is a custom formatter class:

class CustomFormatter extends Formatter {
    @Override
    public String format(LogRecord record) {
        return record.getMessage() + "\n";
    }
    @Override
    public String getHead(Handler h) {
        return "header\n";
    }
}

Here is worker code:

String path = "/tmp/temp2";
FileHandler fileHandler = new FileHandler(path, 300, 5);
fileHandler.setFormatter(new CustomFormatter());

Logger logger = Logger.getLogger("sam.logging");
logger.addHandler(fileHandler);

for(int i = 0; i < 10000; i++)
    logger.log(new LogRecord(Level.INFO, i+" aaaaaaaaaaaaaa."));

And here are example outputs:

[/tmp] -> cat temp2.3
header
9957 aaaaaaaaaaaaaa.
9958 aaaaaaaaaaaaaa.
9959 aaaaaaaaaaaaaa.
9960 aaaaaaaaaaaaaa.


[/tmp] -> cat temp2.1
header
9985 aaaaaaaaaaaaaa.
9986 aaaaaaaaaaaaaa.
9987 aaaaaaaaaaaaaa.
9988 aaaaaaaaaaaaaa.
9989 aaaaaaaaaaaaaa.

Solution

  • You have to create a custom java.util.Formatter and install it on your FileHandler. The Formatter.getHead method is used to write your headers and is called every time the FileHandler is open or rotates. The Formatter.format method would be used in this case to generate one row of data per given LogRecord. So you need to generate (or reuse) one LogRecord every one second and publish it to the FileHandler.