我一直在尝试使用 webflux 配置 spring-boot 2.1 以将访问日志存储在 JSON 中。此外,我需要将协议、状态代码等信息作为单独的 JSON 字段(不是消息的一部分)。查看互联网,我发现了 logstash-logback-encoder。这似乎有我需要的一切。但是在运行时我收到以下错误:
ERROR in ch.qos.logback.core.FileAppender[accessLog] - Appender [accessLog] failed to append. java.lang.ClassCastException: ch.qos.logback.classic.spi.LoggingEvent cannot be cast to ch.qos.logback.access.spi.IAccessEvent
at java.lang.ClassCastException: ch.qos.logback.classic.spi.LoggingEvent cannot be cast to ch.qos.logback.access.spi.IAccessEvent
at at net.logstash.logback.composite.accessevent.AccessEventFormattedTimestampJsonProvider.getTimestampAsMillis(AccessEventFormattedTimestampJsonProvider.java:20)
at at net.logstash.logback.composite.FormattedTimestampJsonProvider.writeTo(FormattedTimestampJsonProvider.java:149)
at at net.logstash.logback.composite.JsonProviders.writeTo(JsonProviders.java:77)
at at net.logstash.logback.composite.CompositeJsonFormatter.writeEventToGenerator(CompositeJsonFormatter.java:189)
at at net.logstash.logback.composite.CompositeJsonFormatter.writeEventToOutputStream(CompositeJsonFormatter.java:166)
at at net.logstash.logback.encoder.CompositeJsonEncoder.encode(CompositeJsonEncoder.java:122)
at at net.logstash.logback.encoder.CompositeJsonEncoder.encode(CompositeJsonEncoder.java:34)
at at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:230)
at at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
at at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
at at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
at at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
at at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
at at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:421)
at at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at at ch.qos.logback.classic.Logger.info(Logger.java:591)
at at reactor.util.Loggers$Slf4JLogger.info(Loggers.java:255)
at at reactor.netty.http.server.AccessLog.log(AccessLog.java:104)
at at reactor.netty.http.server.AccessLogHandler.lambda$write$0(AccessLogHandler.java:77)
at at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)
at at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:504)
at at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:483)
at at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424)
at at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:103)
at at io.netty.util.internal.PromiseNotificationUtil.trySuccess(PromiseNotificationUtil.java:48)
at at io.netty.channel.ChannelOutboundBuffer.safeSuccess(ChannelOutboundBuffer.java:696)
at at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:258)
at at io.netty.channel.nio.AbstractNioByteChannel.doWriteInternal(AbstractNioByteChannel.java:216)
at at io.netty.channel.nio.AbstractNioByteChannel.doWrite0(AbstractNioByteChannel.java:209)
at at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:397)
at at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:934)
at at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:360)
at at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:901)
at at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1396)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768)
at at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749)
at at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.flush(CombinedChannelDuplexHandler.java:533)
at at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:115)
at at io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:358)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768)
at at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749)
at at io.netty.channel.ChannelDuplexHandler.flush(ChannelDuplexHandler.java:117)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768)
at at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749)
at at io.netty.channel.ChannelDuplexHandler.flush(ChannelDuplexHandler.java:117)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
at at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768)
我的配置相当简单:
<appender name="accessLog" class="ch.qos.logback.core.FileAppender">
<file>${LOGS}/access_log.log</file>
<encoder class="net.logstash.logback.encoder.LogstashAccessEncoder"/>
</appender>
<logger name="reactor.netty.http.server.AccessLog" level="DEBUG" additivity="false">
<appender-ref ref="accessLog"/>
</logger>
在这一点上,我被卡住了。我一直在搜索互联网并查看 logback 代码,但我仍然不知道该怎么做才能让 AccessEvent 包含更多信息,而不是 LoggingEvent