That design should be fine but you will need to implement your own 
ContextSelector to locate the LoggerContext from the Map. You will also need to 
make sure the application id is available whenever something needs to locate 
the LoggerContext via the ContextSelector.

As I have said previously, loggerContext.updateLoggers() does not “change an 
application’s configuration”. It causes the Loggers to be remapped to the 
appropriate LoggerContext. You can get the current configuration for the 
LoggerContext and then modify the existing configuration if you do it 
carefully. Whether you need to call updateLoggers depends on what you are 
modifying in the configuration. It only needs to be called if you are adding or 
removing LoggerConfigs or are changing their logging level.

If your applications call LogManager getLogger() your approach may have 
problems. Applications that call that will typically save the Logger that is 
returned and never call getLogger() again. That won’t work since you want 
different Loggers associated with different LoggerContexts based on the 
application id.  The way you have it coded below should work though.

Ralph

> On Oct 2, 2020, at 6:01 AM, Jochen Wiedmann <[email protected]> wrote:
> 
> Hi,
> 
> consider a logging server. Let's say, there's a REST service "log",
> accepting the following parameters:
> 
>   - applicationId
>   - category
>   - level
>   - message
> 
> The purpose here is to use the application id as identification of a
> log4j configuration. So, the implementation would look roughly like
> this:
> 
>    private static final ConcurrentHashMap<String,LoggerContext>
>          applications = new ConcurrentHashMap<>();
>    public void log(String pApplicationId, String pCategory,
>                            String pLevel, String pMessage) {
>        final LoggerContext lc =
>            applications.computeIfAbsent(pApplicationId,
>                (id) -> newLoggerContext(id));
>        final Logger logger = lc.getLogger(pCategory)
>        logger.log(pLevel, message);
>    }
> 
> I hope, I can make myself understandable. Questions:
> 
> 1.) Is that design appropriate? In particular, is the mapping between
> application id, and the LoggerContext (as a representation of the
> log4j configuration) appropriate?
> 2.) Assuming, that I want to change an applications configuration: Is
>         loggerContext.updateLoggers(Configuration)
>     the proper way to do that? If so, is it possible to obtain the current
>     Configuration, modifying it, and then do the update?
> 3.) Did I consider multi-threading properly? Basically, my idea is, that
>     using a ConcurrentHashMap, and computeIfAbsent is sufficient to
>     obtain a LoggerContext. From that point, I would trust in the
> multi-threading abilities of Log4J.
> 
> Thanks,
> 
> Jochen
> 
> --
> 
> Look, that's why there's rules, understand? So that you think before
> you break 'em.
> 
>    -- (Terry Pratchett, Thief of Time)
> 


Reply via email to