GitHub user marc-polizzi added a comment to the discussion: Java CRaC support 
on static defined Loggers

Giving you a single java file might not be easy. But I'll try to explain what 
we would need and what we've hacked until now.

With CRaC, the state (aka., checkpoint) of the JVM process can be stored to 
disk. Then later, the JVM can be started right from this self-contained state 
very quickly. E.g., even the already compiled bytecode is restored.

Before the checkpoint is actually made by the JVM, the application logic has to 
somehow disconnect itself from the external world : for example, files and 
sockets need to be closed. And upon restoration, the application will reconnect 
accordingly to the external world.

For that purpose, CRaC provides an entry point where we can register Resources 
that basically implements two methods : 
```
beforeCheckpoint() {}
afterRestore() {}
```

So ideally, we would need somehow a way to do something like:
```
beforeCheckpoint() {
    LoggerContext.beforeCheckpointLogic()
}
afterRestore() {
    LoggerContext.afterRestoreLogic()
}
```

and having Log4j doing all the magic for the well known appenders ;-)


So far, this is what we've found and are doing assuming we've 
`RollingFileAppender` only - `ConsoleAppender` are working fine out of the box. 
In pseudo-code something like : 
```
beforeCheckpoint() {
    LoggerContext.getConfiguration().getAppenders().forEach( rfa -> 
RollingFileUtils.closeOutputStream( rfa ); )
}
afterRestore() {
    LoggerContext.getConfiguration().getAppenders().forEach( rfa -> 
RollingFileUtils.openOutputStream( rfa ); )
}
```

with the helper code : 
```
    /**
     * Replace the output stream by a NULL output stream and close the file 
output stream.
     */
    public static void closeOutputStream(RollingFileAppender appender)
    {
        final String fn = appender.getFileName();
        final OutputStreamManager manager = appender.getManager();

        if (manager.hasOutputStream())
        {
            try
            {
                final OutputStream os = manager.getOutputStream();

                manager.setOutputStream(NullOutputStream.INSTANCE);

                os.close();

            }
            catch (IOException ex)
            {
                throw new RuntimeException(ex);
            }
        }

    }

    /**
     * Replace the NULL output stream.
     */
    public static void openOutputStream(RollingFileAppender appender)
    {
        final String fn = appender.getFileName();
        final OutputStreamManager manager = appender.getManager();

        try
        {
            final OutputStream os = new FileOutputStream(fn, true);

            manager.setOutputStream(os);
        }
        catch (IOException ex)
        {
            throw new RuntimeException(ex);
        }
    }
```

So far, it seems to work nicely and we are able to checkpoint and restore our 
Java application with Log4j still working as expected. 

It would be nice to have this kind of support built in Log4j somehow. Right 
now, I've the feeling that our code is a bit of a hack ;-)

Let me know if you need more information.

GitHub link: 
https://github.com/apache/logging-log4j2/discussions/3954#discussioncomment-14698503

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to