You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@logging.apache.org by Jochen Wiedmann <jo...@gmail.com> on 2020/10/02 13:01:03 UTC

Maintaining a set of Log4j configurations

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)

Re: Maintaining a set of Log4j configurations

Posted by Ralph Goers <ra...@dslextreme.com>.
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 <jo...@gmail.com> 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)
>