是否有一种方法可以将日志流式传输到Spring Boot应用程序



我有一个弹簧启动应用程序,该应用程序用作事件记录器。每个客户端通过REST API发送不同的事件,然后将其保存在数据库中。但是除了简单的事件外,我还需要客户将执行日志发送到Spring Boot。

现在,在客户端完成执行后,上传日志很容易,那里有很多示例。我需要的是在客户端执行,逐行执行时流式传输日志,而不要等到客户端完成。

我花了很多时间搜索了一个可能的答案,我找不到任何适合我需求的东西。有什么建议如何使用Spring Boot(包括未来版本)?它可行吗?

我在这里看到了几个可能性。首先,考虑使用logback(默认的弹簧启动记录实现)套接字Appappender或客户端中的serversocketappender。请参阅:https://logback.qos.ch/manual/appenders.html。这将使您将日志消息发送到任何记录服务。但是我可能建议您不要登录您的春季启动事件应用程序,因为我怀疑会不必要地增加您的应用程序的复杂性,而且我可以看到事件应用程序中有一些错误的情况,然后导致客户端记录一堆反过来,所有这些错误都返回到事件应用程序,因此很难确定初始错误。

我会谨此建议是,您会登录到登录服务器 - logstash:https://www.elastic.co/products/logstash,或者,如果您已经有一个将事件保存到的DB,则,然后也许使用日志dbappender并将日志直接写入db。

我在这里写了一个示例,介绍了如何在Spring Boot Endpoint中流动文件更新。唯一的区别是代码使用Java WatchService API在给定文件上触发文件更新。

但是,在您的情况下,我还将选择日志appender直接向连接的客户端发送消息(使用SSE -CALL template.broadcast。。

端点:

@GetMapping(path = "/logs", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamSseMvc() {
    return sseService.newSseEmitter();
}

服务:

public class LogsSseService {
private static final Logger log = LoggerFactory.getLogger(LogsSseService.class);
private static final String TOPIC = "logs";
private final SseTemplate template;
private static final AtomicLong COUNTER = new AtomicLong(0);
public LogsSseService(SseTemplate template, MonitoringFileService monitoringFileService) {
    this.template = template;
    monitoringFileService.listen(file -> {
        try {
            Files.lines(file)
                    .skip(COUNTER.get())
                    .forEach(line ->
                            template.broadcast(TOPIC, SseEmitter.event()
                                    .id(String.valueOf(COUNTER.incrementAndGet()))
                                    .data(line)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
}
public SseEmitter newSseEmitter() {
    return template.newSseEmitter(TOPIC);
}

}

自定义appender(您必须添加到记录器 - 在此处检查):

public class StreamAppender extends UnsynchronizedAppenderBase<ILoggingEvent> implements SmartLifecycle {
public static final String TOPIC = "logs";
private final SseTemplate template;
public StreamAppender(SseTemplate template) {
    this.template = template;
}
@Override
protected void append(ILoggingEvent event) {
    template.broadcast(TOPIC, SseEmitter.event()
            .id(event.getThreadName())
            .name("log")
            .data(event.getFormattedMessage()));
}
@Override
public boolean isRunning() {
    return isStarted();
}

}

相关内容

  • 没有找到相关文章

最新更新