3

How can I add current user's details(user email ,...) in every logger.info() method?

it seems

private final Logger logger = LoggerFactory.getLogger(sth.class)

instantiates ch.qos.logback.classic.Loggertype by default.

as far as ch.qos.logback.classic.Logger is a final class so I can't extend to add my functionality.

what is the solution?

raminqdev
  • 69
  • 5

2 Answers2

0

I figured out one way is using MDC. Please check out this link for more information: How to use MDC of logback and SLF4J with spring boot to capture unique tracking in the POST request json?

raminqdev
  • 69
  • 5
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 19 '22 at 10:30
0

This is how I implemented this using Spring Boot v2.7.

First define a custom filter that will add the user data to MDC:

import org.slf4j.MDC
import org.springframework.security.core.AuthenticatedPrincipal
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Component
import org.springframework.web.filter.OncePerRequestFilter
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@Component
class UserMdcFilter : OncePerRequestFilter() {

    companion object {
        private const val USER_MDC_KEY = "user"
    }

    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        val principal = SecurityContextHolder.getContext().authentication?.principal as? AuthenticatedPrincipal
        if (principal != null) {
            val user = principal.name
            MDC.put(USER_MDC_KEY, user)
        }

        try {
            filterChain.doFilter(request, response)
        } finally {
            MDC.remove(USER_MDC_KEY)
        }
    }
}

Then, add the filter in your Spring Security configuration.

// I do it after FilterSecurityInterceptor, otherwise authenticated context is not set
http.addFilterAfter(userMdcFilter, FilterSecurityInterceptor::class.java)

You can view the data by modifying your log pattern to include MDC:

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <Pattern>
            %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr([%mdc]){yellow} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}
        </Pattern>
        <charset>utf8</charset>
    </encoder>
</appender>

This is the default Spring console log pattern, except %clr([%mdc]){yellow} is added.

End result:

2023-05-16 01:23:14.346 DEBUG [,06bfe7e72b5007e0,06bfe7e72b5007e0] 77570 --- [nio-8080-exec-7] [user=bf11c59b-eaca-47cd-a9d4-77cd62181e55] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
edwardmp
  • 6,339
  • 5
  • 50
  • 77