diff --git a/develop/fluentd/conf/fluent.conf b/develop/fluentd/conf/fluent.conf index 51dbd4cf..61cf3cd1 100644 --- a/develop/fluentd/conf/fluent.conf +++ b/develop/fluentd/conf/fluent.conf @@ -11,9 +11,12 @@ @type elasticsearch host elasticsearch + include_tag_key true port 9200 - index_name logs include_timestamp true user elastic password Passw0rd + logstash_format true + logstash_prefix hideout + flush_interval 10s \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..9355b415 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/hideout-core/gradle/wrapper/gradle-wrapper.properties b/hideout-core/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..9355b415 100644 --- a/hideout-core/gradle/wrapper/gradle-wrapper.properties +++ b/hideout-core/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SpringMvcConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SpringMvcConfig.kt index 301762d4..0294603a 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SpringMvcConfig.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SpringMvcConfig.kt @@ -16,8 +16,11 @@ package dev.usbharu.hideout.core.config +import ch.qos.logback.classic.helpers.MDCInsertingServletFilter +import dev.usbharu.hideout.core.infrastructure.springframework.ApplicationRequestLogInterceptor import dev.usbharu.hideout.core.infrastructure.springframework.SPAInterceptor import dev.usbharu.hideout.generate.JsonOrFormModelMethodProcessor +import org.springframework.boot.web.servlet.FilterRegistrationBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.converter.HttpMessageConverter @@ -30,7 +33,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttribu @Configuration class MvcConfigurer( private val jsonOrFormModelMethodProcessor: JsonOrFormModelMethodProcessor, - private val spaInterceptor: SPAInterceptor + private val spaInterceptor: SPAInterceptor, + private val applicationRequestLogInterceptor: ApplicationRequestLogInterceptor ) : WebMvcConfigurer { override fun addArgumentResolvers(resolvers: MutableList) { resolvers.add(jsonOrFormModelMethodProcessor) @@ -38,6 +42,16 @@ class MvcConfigurer( override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(spaInterceptor) + registry.addInterceptor(applicationRequestLogInterceptor) + } + + @Bean + fun mdcFilter(): FilterRegistrationBean { + val bean = FilterRegistrationBean() + bean.filter = MDCInsertingServletFilter() + bean.addUrlPatterns("/*"); + bean.order = Int.MIN_VALUE + return bean } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/ApplicationRequestLogInterceptor.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/ApplicationRequestLogInterceptor.kt new file mode 100644 index 00000000..c368f482 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/ApplicationRequestLogInterceptor.kt @@ -0,0 +1,65 @@ +package dev.usbharu.hideout.core.infrastructure.springframework + +import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.HideoutUserDetails +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.slf4j.MDC +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.jwt.Jwt +import org.springframework.stereotype.Component +import org.springframework.web.servlet.AsyncHandlerInterceptor +import java.util.* + +@Component +class ApplicationRequestLogInterceptor : AsyncHandlerInterceptor { + override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { + MDC.put(requestId, UUID.randomUUID().toString()) + + val userDetailId = when (val principal = SecurityContextHolder.getContext().authentication?.principal) { + is HideoutUserDetails -> { + principal.userDetailsId + } + + is Jwt -> { + principal.getClaim("uid")?.toLongOrNull() + } + + else -> { + null + } + } + + if (userDetailId != null) { + MDC.put(userId, userDetailId.toString()) + } + + return true + } + + override fun afterCompletion( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ex: Exception? + ) { + removeMdc() + } + + override fun afterConcurrentHandlingStarted( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any + ) { + removeMdc() + } + + private fun removeMdc() { + MDC.remove(requestId) + MDC.remove(userId) + } + + companion object { + const val requestId: String = "requestId" + const val userId: String = "userId" + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt index 5ca4964e..713374bd 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt @@ -21,6 +21,7 @@ import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.slf4j.MDCContext import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.core.userdetails.UsernameNotFoundException @@ -33,7 +34,7 @@ class UserDetailsServiceImpl( private val applicationConfig: ApplicationConfig, private val transaction: Transaction, ) : UserDetailsService { - override fun loadUserByUsername(username: String?): UserDetails = runBlocking { + override fun loadUserByUsername(username: String?): UserDetails = runBlocking(MDCContext()) { if (username == null) { throw UsernameNotFoundException("Username not found") } diff --git a/hideout-core/src/main/resources/logback-spring.xml b/hideout-core/src/main/resources/logback-spring.xml index a29f493e..dfb52736 100644 --- a/hideout-core/src/main/resources/logback-spring.xml +++ b/hideout-core/src/main/resources/logback-spring.xml @@ -1,7 +1,7 @@ - + diff --git a/hideout-mastodon/gradle/wrapper/gradle-wrapper.properties b/hideout-mastodon/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..9355b415 100644 --- a/hideout-mastodon/gradle/wrapper/gradle-wrapper.properties +++ b/hideout-mastodon/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringAccountApi.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringAccountApi.kt index caac2717..a9471098 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringAccountApi.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringAccountApi.kt @@ -49,6 +49,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.slf4j.MDCContext import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller @@ -164,7 +165,7 @@ class SpringAccountApi( id: List?, withSuspended: Boolean ): ResponseEntity> { - val principal = runBlocking { principalContextHolder.getPrincipal() } + val principal = runBlocking(MDCContext()) { principalContextHolder.getPrincipal() } return ResponseEntity.ok(id.orEmpty().asFlow().mapNotNull { fetchRelationship(it, principal).body }) } diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringTimelineApi.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringTimelineApi.kt index 9f259736..f3cc511c 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringTimelineApi.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringTimelineApi.kt @@ -28,6 +28,7 @@ import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Status import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.slf4j.MDCContext import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller @@ -44,7 +45,7 @@ class SpringTimelineApi( sinceId: String?, minId: String?, limit: Int? - ): ResponseEntity> = runBlocking { + ): ResponseEntity> = runBlocking(MDCContext()) { val principal = principalContextHolder.getPrincipal() val userDetail = transaction.transaction { userDetailRepository.findByActorId(principal.actorId.id)