You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-user@logging.apache.org by Dawid Weiss <da...@gmail.com> on 2021/10/27 18:05:12 UTC

Temporarily store/restore the current configuration

Hello,

I've been looking for a solution to a problem and I can't figure out
the solution. I have test code that recursively calls certain routines
which emit quite a bit of logging to the console. I'd like to
temporarily switch the configuration to one that is less chatty, but
restore the previous configuration afterward.

I looked at the LoggerContext and its reconfigure(Configuration) and
setConfiguration(Configuration) methods, thinking something like this
would work:

var ctx = (LoggerContext) LogManager.getContext(false);
var current = ctx.getConfiguration();
try {
  ctx.setConfiguration(myQuietConfiguration);
  otherCode();
} finally {
  ctx.setConfiguration(current);
}

But it doesn't. Neither with reconfigure nor with setConfiguration.
The root logger's appender is never reattached properly.

I wonder what I'm missing here. I've tried several other avenues but I
will spare you the code as none of them worked properly. Any help
would be greatly appreciated.

Dawid

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Re: Temporarily store/restore the current configuration

Posted by Dawid Weiss <da...@gmail.com>.
Thanks for confirming, Ralph. I'd seriously consider adding a
state-check assertion in the code to just throw something reasonable
at folks like me who try to do such hacks - would save tons of time
and code-digging. :)

Dawid

On Tue, Nov 9, 2021 at 4:57 PM Ralph Goers <ra...@dslextreme.com> wrote:
>
> Sorry for not replying sooner but yes, that was going to be my response. Once
> stopped a Configuration cannot be restarted.
>
> I have wanted to be able to provide an easy way to clone a configuration but
> have never gotten around to it. This would be useful if you have modified the c
> onfiguration after it initialized
>
> We have also discussed having the configuration be able to serialize itself back
> into a configuration file but again, no one has attempted to do it.
>
> Ralph
>
> > On Nov 9, 2021, at 5:15 AM, Dawid Weiss <da...@gmail.com> wrote:
> >
> > So I took a closer look and even found another place in my code where
> > I previously had the same problem... setConfiguration() won't work in
> > my
> > example code - ever. Seems like Configuration objects are not meant to
> > be reused at all. They have an internal state (lifecycle) and, once
> > stopped, they're effectively unusable. So, when you try to do this:
> >
> > var ctx = (LoggerContext) LogManager.getContext(false);
> > var current = ctx.getConfiguration();
> > try {
> >  ctx.setConfiguration(myQuietConfiguration);
> >  otherCode();
> > } finally {
> >  ctx.setConfiguration(current);
> > }
> >
> > what happens is the "current" configuration is stopped and internally
> > will never reinitialize all the appenders (and internals) again.
> > Here's why:
> >
> > https://github.com/apache/logging-log4j2/blob/0043e9238af0efd9dbce462463e0fa1bf14e35b0/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java#L290-L292
> >
> > The initialization routine calls doConfigure which in turn does all
> > the tricky stuff adding appenders, etc. I'm not sure whether this is
> > intentional or not but if Configuration objects are not meant for
> > reuse then I'd throw an exception if they're in illegal state (in
> > ctx.setConfiguration)... this would make it much easier to figure out.
> > And if there should be a way to reuse them then I think it's a bug
> > somewhere because it currently doesn't work (even on the simplest of
> > examples).
> >
> > Incidentally, you can reinitialize the configuration from scratch -
> > then everything works like a charm, no need to call updateLoggers
> > (it's done internally):
> >
> > LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
> > URI previousConfiguration = ctx.getConfigLocation();
> > ctx.setConfigLocation(newConfigLocation);
> > try {
> >  otherCode();
> > } finally {
> >  ctx.setConfigLocation(previousConfiguration);
> > }
> >
> > Of course it requires re-parsing the configuration multiple times so
> > is not ideal.
> >
> > I'd love to hear from the developers about what they think in terms of
> > the Configuration object reuse/ lifecycle.
> >
> > Dawid
> >
> >
> > On Tue, Nov 9, 2021 at 10:30 AM Dawid Weiss <da...@gmail.com> wrote:
> >>
> >>
> >> Hi Chris!
> >>
> >> Small world, eh? :)
> >>
> >>> Dawid: The piece you're missing is LoggerContext.updateLoggers(...)
> >>
> >>
> >> I did that too... I think. I have dynamic appender redirection (teeing) in another place - this is where updateLoggers() is used. But this time I wanted to swap out entire configurations (this may involve different logger setup, appenders, etc.) and could't make it work properly, no matter what. I'll go back to the drawing board and retry.
> >>
> >> I do understand it's not a typical use-case but it's actually a fairly frequent thing that happens in integration tests when you don't want to see stuff
> >> that is tested (well, maybe you do, but only if something fails).
> >>
> >> Dawid
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
> > For additional commands, e-mail: log4j-user-help@logging.apache.org
> >
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-user-help@logging.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Re: Temporarily store/restore the current configuration

Posted by Ralph Goers <ra...@dslextreme.com>.
Sorry for not replying sooner but yes, that was going to be my response. Once 
stopped a Configuration cannot be restarted. 

I have wanted to be able to provide an easy way to clone a configuration but 
have never gotten around to it. This would be useful if you have modified the c
onfiguration after it initialized 

We have also discussed having the configuration be able to serialize itself back 
into a configuration file but again, no one has attempted to do it.

Ralph

> On Nov 9, 2021, at 5:15 AM, Dawid Weiss <da...@gmail.com> wrote:
> 
> So I took a closer look and even found another place in my code where
> I previously had the same problem... setConfiguration() won't work in
> my
> example code - ever. Seems like Configuration objects are not meant to
> be reused at all. They have an internal state (lifecycle) and, once
> stopped, they're effectively unusable. So, when you try to do this:
> 
> var ctx = (LoggerContext) LogManager.getContext(false);
> var current = ctx.getConfiguration();
> try {
>  ctx.setConfiguration(myQuietConfiguration);
>  otherCode();
> } finally {
>  ctx.setConfiguration(current);
> }
> 
> what happens is the "current" configuration is stopped and internally
> will never reinitialize all the appenders (and internals) again.
> Here's why:
> 
> https://github.com/apache/logging-log4j2/blob/0043e9238af0efd9dbce462463e0fa1bf14e35b0/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java#L290-L292
> 
> The initialization routine calls doConfigure which in turn does all
> the tricky stuff adding appenders, etc. I'm not sure whether this is
> intentional or not but if Configuration objects are not meant for
> reuse then I'd throw an exception if they're in illegal state (in
> ctx.setConfiguration)... this would make it much easier to figure out.
> And if there should be a way to reuse them then I think it's a bug
> somewhere because it currently doesn't work (even on the simplest of
> examples).
> 
> Incidentally, you can reinitialize the configuration from scratch -
> then everything works like a charm, no need to call updateLoggers
> (it's done internally):
> 
> LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
> URI previousConfiguration = ctx.getConfigLocation();
> ctx.setConfigLocation(newConfigLocation);
> try {
>  otherCode();
> } finally {
>  ctx.setConfigLocation(previousConfiguration);
> }
> 
> Of course it requires re-parsing the configuration multiple times so
> is not ideal.
> 
> I'd love to hear from the developers about what they think in terms of
> the Configuration object reuse/ lifecycle.
> 
> Dawid
> 
> 
> On Tue, Nov 9, 2021 at 10:30 AM Dawid Weiss <da...@gmail.com> wrote:
>> 
>> 
>> Hi Chris!
>> 
>> Small world, eh? :)
>> 
>>> Dawid: The piece you're missing is LoggerContext.updateLoggers(...)
>> 
>> 
>> I did that too... I think. I have dynamic appender redirection (teeing) in another place - this is where updateLoggers() is used. But this time I wanted to swap out entire configurations (this may involve different logger setup, appenders, etc.) and could't make it work properly, no matter what. I'll go back to the drawing board and retry.
>> 
>> I do understand it's not a typical use-case but it's actually a fairly frequent thing that happens in integration tests when you don't want to see stuff
>> that is tested (well, maybe you do, but only if something fails).
>> 
>> Dawid
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-user-help@logging.apache.org
> 
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Re: Fwd: Temporarily store/restore the current configuration

Posted by Dawid Weiss <da...@gmail.com>.
So I took a closer look and even found another place in my code where
I previously had the same problem... setConfiguration() won't work in
my
example code - ever. Seems like Configuration objects are not meant to
be reused at all. They have an internal state (lifecycle) and, once
stopped, they're effectively unusable. So, when you try to do this:

var ctx = (LoggerContext) LogManager.getContext(false);
var current = ctx.getConfiguration();
try {
  ctx.setConfiguration(myQuietConfiguration);
  otherCode();
} finally {
  ctx.setConfiguration(current);
}

what happens is the "current" configuration is stopped and internally
will never reinitialize all the appenders (and internals) again.
Here's why:

https://github.com/apache/logging-log4j2/blob/0043e9238af0efd9dbce462463e0fa1bf14e35b0/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java#L290-L292

The initialization routine calls doConfigure which in turn does all
the tricky stuff adding appenders, etc. I'm not sure whether this is
intentional or not but if Configuration objects are not meant for
reuse then I'd throw an exception if they're in illegal state (in
ctx.setConfiguration)... this would make it much easier to figure out.
And if there should be a way to reuse them then I think it's a bug
somewhere because it currently doesn't work (even on the simplest of
examples).

Incidentally, you can reinitialize the configuration from scratch -
then everything works like a charm, no need to call updateLoggers
(it's done internally):

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
URI previousConfiguration = ctx.getConfigLocation();
ctx.setConfigLocation(newConfigLocation);
try {
  otherCode();
} finally {
  ctx.setConfigLocation(previousConfiguration);
}

Of course it requires re-parsing the configuration multiple times so
is not ideal.

I'd love to hear from the developers about what they think in terms of
the Configuration object reuse/ lifecycle.

Dawid


On Tue, Nov 9, 2021 at 10:30 AM Dawid Weiss <da...@gmail.com> wrote:
>
>
> Hi Chris!
>
> Small world, eh? :)
>
>> Dawid: The piece you're missing is LoggerContext.updateLoggers(...)
>
>
> I did that too... I think. I have dynamic appender redirection (teeing) in another place - this is where updateLoggers() is used. But this time I wanted to swap out entire configurations (this may involve different logger setup, appenders, etc.) and could't make it work properly, no matter what. I'll go back to the drawing board and retry.
>
> I do understand it's not a typical use-case but it's actually a fairly frequent thing that happens in integration tests when you don't want to see stuff
> that is tested (well, maybe you do, but only if something fails).
>
> Dawid

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Re: Fwd: Temporarily store/restore the current configuration

Posted by Dawid Weiss <da...@gmail.com>.
Hi Chris!

Small world, eh? :)

Dawid: The piece you're missing is LoggerContext.updateLoggers(...)


I did that too... I think. I have dynamic appender redirection (teeing) in
another place - this is where updateLoggers() is used. But this time I
wanted to swap out entire configurations (this may involve different logger
setup, appenders, etc.) and could't make it work properly, no matter what.
I'll go back to the drawing board and retry.

I do understand it's not a typical use-case but it's actually a fairly
frequent thing that happens in integration tests when you don't want to see
stuff
that is tested (well, maybe you do, but only if something fails).

Dawid

Re: Fwd: Temporarily store/restore the current configuration

Posted by Chris Hostetter <ho...@fucit.org>.
: var ctx = (LoggerContext) LogManager.getContext(false);
: var current = ctx.getConfiguration();
: try {
:   ctx.setConfiguration(myQuietConfiguration);
:   otherCode();
: } finally {
:   ctx.setConfiguration(current);
: }
: 
: But it doesn't. Neither with reconfigure nor with setConfiguration.
: The root logger's appenders are never reattached properly.
: 
: I wonder what I'm missing here. I've tried several other avenues but I

Dawid: The piece you're missing is LoggerContext.updateLoggers(...)

You can see examples of what you're describing in Solr's @LogLevel 
and ErrorLogMuter ...

https://github.com/apache/solr/blob/main/solr/test-framework/src/java/org/apache/solr/util/LogLevel.java
https://github.com/apache/solr/blob/main/solr/test-framework/src/java/org/apache/solr/util/ErrorLogMuter.java



-Hoss

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Fwd: Temporarily store/restore the current configuration

Posted by Dawid Weiss <da...@gmail.com>.
Hello,

I've been looking at a seemingly simple problem I can't figure out the
solution for - hope it's something you've encountered before.

I have test code that recursively calls certain routines
which emit quite a bit of logging to the console. I'd like to
temporarily switch the logging configuration to one that is less chatty, but
restore the previous configuration afterward (as if nothing changed). Everything
is single-threaded.

I looked at the LoggerContext and its reconfigure(Configuration) and
setConfiguration(Configuration) methods, thinking something like this
would work:

var ctx = (LoggerContext) LogManager.getContext(false);
var current = ctx.getConfiguration();
try {
  ctx.setConfiguration(myQuietConfiguration);
  otherCode();
} finally {
  ctx.setConfiguration(current);
}

But it doesn't. Neither with reconfigure nor with setConfiguration.
The root logger's appenders are never reattached properly.

I wonder what I'm missing here. I've tried several other avenues but I
will spare you the code as none of them worked properly. Any help or pointers
would be greatly appreciated.

Dawid

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org