From 72bcfbe6e57462c0e469aa3ff1032545605867d5 Mon Sep 17 00:00:00 2001 From: Shivam Nagpal Date: Fri, 26 Apr 2024 02:21:22 +0530 Subject: [PATCH 1/2] feature: #29 | Add the values from log string to MDC --- .../workout/manager/filters/CorsFilter.kt | 2 +- .../manager/filters/HttpLoggingFilter.kt | 20 ++++++++++++---- .../shivam/workout/manager/utils/Constants.kt | 3 +++ .../workout/manager/utils/Slf4jUtils.kt | 24 +++++++++++++++++++ src/main/resources/application.properties | 2 +- 5 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Slf4jUtils.kt diff --git a/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/CorsFilter.kt b/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/CorsFilter.kt index cac0bdb..e589f89 100644 --- a/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/CorsFilter.kt +++ b/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/CorsFilter.kt @@ -9,7 +9,7 @@ import org.springframework.core.annotation.Order import org.springframework.stereotype.Component import org.springframework.web.filter.OncePerRequestFilter -@Component +@Component("customCorsFilter") @Order(value = FilterOrderingConstants.CORS_FILTER_ORDER) class CorsFilter : OncePerRequestFilter() { override fun doFilterInternal( diff --git a/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/HttpLoggingFilter.kt b/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/HttpLoggingFilter.kt index 774598a..d160186 100644 --- a/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/HttpLoggingFilter.kt +++ b/src/main/kotlin/com/nagpal/shivam/workout/manager/filters/HttpLoggingFilter.kt @@ -2,11 +2,11 @@ package com.nagpal.shivam.workout.manager.filters import com.nagpal.shivam.workout.manager.utils.Constants import com.nagpal.shivam.workout.manager.utils.FilterOrderingConstants +import com.nagpal.shivam.workout.manager.utils.Slf4jUtils import jakarta.servlet.FilterChain import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.slf4j.LoggerFactory -import org.slf4j.MDC import org.springframework.core.annotation.Order import org.springframework.stereotype.Component import org.springframework.web.filter.OncePerRequestFilter @@ -21,10 +21,20 @@ class HttpLoggingFilter : OncePerRequestFilter() { response: HttpServletResponse, filterChain: FilterChain, ) { - MDC.put(Constants.REQUEST_ID, request.getAttribute(Constants.REQUEST_ID) as String) - filterChain.doFilter(request, response) - log.info("Request to {}: {} - {}", request.method, formURI(request), response.status) - MDC.remove(Constants.REQUEST_ID) + Slf4jUtils.mdcPutMulti( + mapOf( + Pair(Constants.REQUEST_ID, request.getAttribute(Constants.REQUEST_ID) as String), + Pair(Constants.HTTP_METHOD, request.method), + Pair(Constants.PATH, formURI(request)), + ), + ) + .use { + log.info("HTTP Request received") + filterChain.doFilter(request, response) + Slf4jUtils.mdcPut(Constants.HTTP_STATUS, response.status.toString()).use { + log.info("HTTP Request responded") + } + } } private fun formURI(request: HttpServletRequest): String { diff --git a/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Constants.kt b/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Constants.kt index cdc2f3a..c1ab8c1 100644 --- a/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Constants.kt +++ b/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Constants.kt @@ -13,5 +13,8 @@ object Constants { const val USER_ID = "userId" const val ROLES = "roles" const val REQUEST_ID = "requestId" + const val HTTP_METHOD = "httpMethod" + const val PATH = "path" + const val HTTP_STATUS = "status" const val REQUEST_ARRIVAL_TIME = "requestArrivalTime" } diff --git a/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Slf4jUtils.kt b/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Slf4jUtils.kt new file mode 100644 index 0000000..a39d3df --- /dev/null +++ b/src/main/kotlin/com/nagpal/shivam/workout/manager/utils/Slf4jUtils.kt @@ -0,0 +1,24 @@ +package com.nagpal.shivam.workout.manager.utils + +import org.slf4j.MDC +import java.io.Closeable + +object Slf4jUtils { + class MDCMultiCloseable(private val keys: Set) : Closeable { + override fun close() { + keys.forEach { MDC.remove(it) } + } + } + + fun mdcPut(key: String, value: String): MDCMultiCloseable { + MDC.put(key, value) + return MDCMultiCloseable(setOf(key)) + } + + fun mdcPutMulti(entryMap: Map): MDCMultiCloseable { + entryMap.forEach { + MDC.put(it.key, it.value) + } + return MDCMultiCloseable(entryMap.keys) + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3eb9bfb..74b9f95 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -10,6 +10,6 @@ spring.jpa.hibernate.ddl-auto=validate # Show message in error server.error.include-message=always # Logging file path -logging.pattern.level=%5p %highlight(%X{requestId}) +logging.pattern.level=%5p %highlight(%X) logging.file.path=logs auth.token.public.key=${AUTH_TOKEN_PUBLIC_KEY} From cbff4ed89d74acdeca4bc06ff5b08691935e8d5d Mon Sep 17 00:00:00 2001 From: Shivam Nagpal Date: Fri, 26 Apr 2024 03:12:45 +0530 Subject: [PATCH 2/2] feature: #29 | Add the JSON Log Encoder for the LogBack --- build.gradle.kts | 1 + libs.versions.toml | 2 ++ .../resources/application-staging.properties | 1 + src/main/resources/logback-json.xml | 21 +++++++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 src/main/resources/application-staging.properties create mode 100644 src/main/resources/logback-json.xml diff --git a/build.gradle.kts b/build.gradle.kts index 6f73704..dc68a72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(libs.flyway.core) implementation(libs.auth0.jwt) implementation(libs.kotlin.reflect) + implementation(libs.logback.logstash.encoder) developmentOnly(libs.spring.boot.devtools) diff --git a/libs.versions.toml b/libs.versions.toml index c85c71d..150b664 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -2,6 +2,7 @@ apache-commons-text = "1.11.0" auth0-jwt = "3.18.3" kotlin-plugin = "1.9.23" +logback-logstash-encoder = "7.4" spotless = "6.21.0" spring-boot = "3.2.4" spring-dependency-management = "1.1.4" @@ -14,6 +15,7 @@ flyway-core = { module = "org.flywaydb:flyway-core" } jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" } jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" } +logback-logstash-encoder = { module = "net.logstash.logback:logstash-logback-encoder", version.ref = "logback-logstash-encoder" } postgresql = { module = "org.postgresql:postgresql" } springdoc-webmvc-ui = { module = "org.springdoc:springdoc-openapi-starter-webmvc-ui", version.ref = "spring-doc" } spring-boot-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator" } diff --git a/src/main/resources/application-staging.properties b/src/main/resources/application-staging.properties new file mode 100644 index 0000000..ccd4e05 --- /dev/null +++ b/src/main/resources/application-staging.properties @@ -0,0 +1 @@ +logging.config=classpath:logback-json.xml diff --git a/src/main/resources/logback-json.xml b/src/main/resources/logback-json.xml new file mode 100644 index 0000000..dfe9719 --- /dev/null +++ b/src/main/resources/logback-json.xml @@ -0,0 +1,21 @@ + + + + + + timestamp + + + + + + + + + + + + + + +