diff --git a/README.md b/README.md index de54ddc..7b8f1bb 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,7 @@ * autologging * serializer + +## logger-spring-web + +Interceptor для логирования запросов/ответов. diff --git a/logger-spring-web/build.gradle.kts b/logger-spring-web/build.gradle.kts new file mode 100644 index 0000000..4029533 --- /dev/null +++ b/logger-spring-web/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("kotlin") + id("kotlin-spring") + id("maven-publish") +} + +dependencies { + api(project(":logger-spring")) + + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + + implementation(project(":common-spring-web")) + + implementation("org.springframework.boot:spring-boot-starter-web") +} diff --git a/logger-spring-web/src/main/kotlin/ru/touchin/logger/spring/web/interceptors/LoggingInterceptor.kt b/logger-spring-web/src/main/kotlin/ru/touchin/logger/spring/web/interceptors/LoggingInterceptor.kt new file mode 100644 index 0000000..4530c00 --- /dev/null +++ b/logger-spring-web/src/main/kotlin/ru/touchin/logger/spring/web/interceptors/LoggingInterceptor.kt @@ -0,0 +1,93 @@ +@file:Suppress("unused") +package ru.touchin.logger.spring.web.interceptors + +import org.springframework.http.HttpStatus +import org.springframework.web.servlet.HandlerInterceptor +import ru.touchin.common.spring.web.dto.ApiError +import ru.touchin.common.spring.web.request.RequestUtils.publicIp +import ru.touchin.logger.context.DefaultContextFields +import ru.touchin.logger.context.LoggerExecutionContext +import ru.touchin.logger.dto.LogData +import ru.touchin.logger.dto.LogDuration +import ru.touchin.logger.factory.LogBuilderFactory +import java.net.URI +import java.util.* +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +class LoggingInterceptor( + private val logBuilderFactory: LogBuilderFactory, +) : HandlerInterceptor { + + private val logDuration = LogDuration() + + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any + ): Boolean { + if (request.requestURI.let(::URI).path == ERROR_PATH) { + return true + } + + val uri = request.requestURI.let(::URI) + + LoggerExecutionContext.current.updateContext { context -> + context.plus(DefaultContextFields.id.name to UUID.randomUUID().toString()) + context.plus(DefaultContextFields.host.name to uri.host) + context.plus(DefaultContextFields.path.name to uri.path) + context.plus(DefaultContextFields.httpMethod.name to request.method) + context.plus(DefaultContextFields.ipAddress.name to request.publicIp) + } + + logBuilderFactory.create(this::class.java) + .addTags(API_TAG, REQUEST_TAG) + .build() + .log() + + return true + } + + override fun afterCompletion( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ex: Exception? + ) { + if (request.requestURI.let(::URI).path == ERROR_PATH) { + return + } + + LoggerExecutionContext.current.updateContext { data -> + val appCode = data[DefaultContextFields.appCode.name] ?: getAppCode(response) + + appCode + ?.let { data.plus(DefaultContextFields.appCode.name to it) } + ?: data + } + + logBuilderFactory.create(this::class.java) + .setDuration(logDuration) + .addData("httpStatusCode" to response.status) + .addTags(API_TAG, RESPONSE_TAG) + .build() + .log() + + } + + private fun getAppCode(response: HttpServletResponse) = when (response.status) { + HttpStatus.OK.value() -> ApiError.SUCCESS_CODE + HttpStatus.NOT_FOUND.value() -> null + HttpStatus.BAD_REQUEST.value() -> null + else -> ApiError.FAILURE_CODE + } + + companion object { + private const val ERROR_PATH = "/error" + + private const val API_TAG = "api" + private const val REQUEST_TAG = "request" + private const val RESPONSE_TAG = "response" + } + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 6871629..7c6792a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,3 +27,4 @@ include("common-spring-test") include("common-spring-test-jpa") include("logger") include("logger-spring") +include("logger-spring-web")