One tricky task came recently out with feature we were implementing. Fetch Java logs in memory and save them to the database. This pretty clear goal turned out to be not as trivial task as we thought. At the same time, it turned out to be realizable in the short time after some research.
First things first, we had to track down which logging framework is used. We use lombok in our projects which has annotation @Slf4j. But this doesn't tell us anything about implementation and slf4j is only simple API. Since our project uses plain Spring Boot, default logging framework is Logback. Just to be sure, we can do a simple class name check if the package name is wchich we expect.
Once we are sure the log object is indeed Logback, we can cast slf4j interface to ch.qos.logback.classic.Logger and access the log object directly. This opens up new possibility how to reach our goal. Using Appenders. Appender is basically a log output. In our case, we created a custom one which inherits from AppenderBase<ILoggingEvent>. Injecting our code is as simple as overriding append(ILoggingEvent eventObject) method and adding the desired behavior.
At this point, we are ready to do anything we want with ILoggingEvent event object. We can save them to memory, print to String, persist them. In the last step, appender is created, configured, set to ROOT logger and started.
LogAppender logAppender = new LogAppender(); LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); logAppender.setContext(loggerContext); Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); root.addAppender(logAppender); logAppender.start(); |
Once the appender is started, it starts receiving event messages which are handled by our code. The whole process is actually pretty simple but when you only work with file logs, it can be tricky to find the right solution for your use case.
Comments