Each concurrent http request will be served by seperate threads, however, when a request is finished, the same thread may be reused to serve additional requests. This is normal in a webserver.
If you set up a request listener or filter, it will be called at the start of every request. In this listener, you can set an id. Depending on the technology stack you are using there are different ways of accomplishing this.
Ex:
public void requestInitialized(ServletRequestEvent sre){
MDC.put( "userId", new UUID() );
}
or
public void doFilter(...){
MDC.put( "userId", new UUID() );
MDC.put( ... ... );
chain.doFilter(args);
}
This UUID can then be accessed in your logging statement automatically. In your code, you would use normal logging statements:
logger.info("some log info").
Your Appender would be configured with the particular parameter in its string. Ex:
<param name="ConversionPattern" value="RequestUUID: %X{userId} %d{ISO8601} %-5p %c{1} - %m%n" />
Then your logger would automatically printout your log as something like:
Since the MDC var is overwritten at the start of every request, you can be assured that the thread will contain the appropriate value for that request. And since all concurrent requests are handled by independent threads, there will be no overlapping.
You should be able to find plenty of resources/tutorials for ways to use MDC online (stackoverflow or other). Here's a quick primer:
Hope this clarifies things a little. Let me know if anything is still unclear.
Thanks,
Eric