修复由于连接被客户端取消而造成的日志记录器的意外错误

This commit is contained in:
洛洛希雅Lolosia 2024-05-21 15:22:17 +08:00
parent bcbba32201
commit cf60546e29
2 changed files with 26 additions and 19 deletions

View File

@ -2,6 +2,7 @@ package top.lolosia.web.interceptor
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.NullNode import com.fasterxml.jackson.databind.node.NullNode
import kotlinx.coroutines.isActive
import top.lolosia.web.util.bundle.bundleScope import top.lolosia.web.util.bundle.bundleScope
import top.lolosia.web.util.kotlin.pass import top.lolosia.web.util.kotlin.pass
import kotlinx.coroutines.reactor.awaitSingleOrNull import kotlinx.coroutines.reactor.awaitSingleOrNull
@ -48,7 +49,9 @@ class ErrorWebFilter : OrderedWebFilter {
else if (e::class.qualifiedName == "kotlinx.coroutines.JobCancellationException") pass else if (e::class.qualifiedName == "kotlinx.coroutines.JobCancellationException") pass
else logger.error(e.message, e) else logger.error(e.message, e)
if (exchange.response.isCommitted) return@mono // 如果响应体被提交,或者连接被切断,直接返回
if (exchange.response.isCommitted || !isActive) return@mono
val obj = bundleScope { val obj = bundleScope {
"data" set NullNode.instance "data" set NullNode.instance

View File

@ -62,7 +62,8 @@ class LogWebFilter : OrderedWebFilter, CoroutineScope {
fun time(s: Long) = if (s < 10000) String.format("%4dms", s) fun time(s: Long) = if (s < 10000) String.format("%4dms", s)
else String.format("%5ds", s / 1000) else String.format("%5ds", s / 1000)
// 请求处理步骤 // 请求处理步骤
val reqJob = launch { // 防止被客户端断开连接而意外取消日志记录器
val reqJob = CoroutineScope(NonCancellable).launch {
try { try {
val f = suspend { val f = suspend {
var bytes: ByteArray? = null var bytes: ByteArray? = null
@ -76,7 +77,7 @@ class LogWebFilter : OrderedWebFilter, CoroutineScope {
if (str.length > 200) str = str.s200() if (str.length > 200) str = str.s200()
logger.value.info("$up $str") logger.value.info("$up $str")
} }
if (url.startsWith("/api/")) f() if (url.startsWith("/home/api/")) f()
else writeInfo = f else writeInfo = f
} catch (_: Throwable) { } catch (_: Throwable) {
} }
@ -102,24 +103,27 @@ class LogWebFilter : OrderedWebFilter, CoroutineScope {
if (e is HttpStatusCodeException) code = e.statusCode.value() if (e is HttpStatusCodeException) code = e.statusCode.value()
throw e throw e
} finally { } finally {
val f = suspend { // 避免因客户端断开连接而捕获不到信息
// 响应处理步骤 CoroutineScope(NonCancellable).launch {
val length = data.length val f = suspend {
if (length > 200) data = data.s200() // 响应处理步骤
val end1 = System.currentTimeMillis() val length = data.length
// 消费掉请求体,避免由于空请求体导致下方的方法死锁。 if (length > 200) data = data.s200()
request.consume() val end1 = System.currentTimeMillis()
// 等待请求处理完成 // 消费掉请求体,避免由于空请求体导致下方的方法死锁。
reqJob.join() request.consume()
if (code in 200 until 400) { // 等待请求处理完成
logger.value.info("$down${time(end1 - start)}$end $data") reqJob.join()
} else { if (code in 200 until 400) {
writeInfo?.let { it() } logger.value.info("$down${time(end1 - start)}$end $data")
logger.value.warn("$err0 \u001B[1;30;43m $code $err1 $data $end") } else {
writeInfo?.let { it() }
logger.value.warn("$err0 \u001B[1;30;43m $code $err1 $data $end")
}
} }
if (url.startsWith("/home/api/")) f()
else if (code !in 200 until 400) f()
} }
if (url.startsWith("/api/")) f()
else if (code !in 200 until 400) f()
} }
}.then() }.then()
} }