For some story, we used to have an application in microservices architecture, and all services included and used a common dependency library. It was later decided, the microservices approach wasn’t justified and had more overhead than benefit, and eventually was refactored into a modular monolith. Everything is nice and solid, except for one problem. Now everything is being logged into one place, and log entries from common module are less obvious wrt which part of code called it. If previously (microservices) the structure was
service-a.log: ---- ServiceA: doing this Common DB service: calling DB with x <-- obviously called by service A
service-b.log: ---- ServiceB: doing that Common DB service: calling DB with y <-- obviously called by service B
now (with monolith) we have everything in one heap
webapp.log: ---- ServiceA: doing this ServiceB: doing that Common DB service: calling DB with x <-- called by what? Common DB service: calling DB with y <-- called by what?
and this isn’t ideal. Yes, I know I can track around using thread names, but it would be much more pleasant if the separation was done on file level. It’s obvious how to direct service A and service B logs to separate files. But how to do it with Common DB service? Is this feasible? I’m looking for a solution that wouldn’t be intrusive to the services themselves, ie that I could still keep having something simple like
@Slf4j @Service public class CommonDBService { ... }
with no extra logging configuration logic in the service
Advertisement
Answer
It seems my googling abilities had let me down. The solution was to use Mapped Diagnostic Context, which allows associating bits of information with the thread. I put current module value into MDC by making a high priority filter, which which extracts and saves first segment of the path. How that bit of information in MDC is used to direct to specific file is logging backend-specific, but in a case with logback it’s through SiftingAppender.