Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reconfigure log4j2 programmatically #419

Open
raubel opened this issue Dec 15, 2021 · 4 comments
Open

Reconfigure log4j2 programmatically #419

raubel opened this issue Dec 15, 2021 · 4 comments

Comments

@raubel
Copy link

raubel commented Dec 15, 2021

Hi,

I would like to reconfigure log4j2 after initialisation using an Xml Configuration provided by a UI (i.e. not persisted to a file).
However, it looks like pax-logging with log4j2 backend only supports configuration by a set of log4j2 properties (but we do not want that) or by the path to a log4j2 configuration file (but we do not want to persist the UI configuration to a temporary file).

Is there a way to pass a log4j2 XmlConfiguration to log4j2 through pax-logging?
Or would a direct reconfiguration of log4j2 (using log4j2 Configurator) in the context of pax-logging and OSGI work?

Any help would be greatly appreciated.
Rémi

@rmischke-dlr
Copy link

We have faced a similar situation, and I think I have found a setup that works. It is not pretty, as it triggers the reconfiguration of the log4j2 backend via reflection, which ignores the implementation's encapsulation. It seems to work fine so far, though, and I'm fairly optimistic that even if it breaks on a future pax-logging upgrade, it should be easy to adapt.

I have not actively looked for a way to completely configure the backend without any configuration file. What we do, however, is loading an XML configuration file that is parameterized with several system properties ("${sys:...}"). These can be then changed at runtime, and after triggering a reconfiguration (as below), the new settings are applied.

To trigger the reconfiguration, the core part is getting hold of the single runtime instance of org.ops4j.pax.logging.log4j2.internal.PaxLoggingServiceImpl, and then calling update(null) on it -- just like the bundle activator does on configuration changes. To get that instance, I first fetched the registered OSGi service for "org.ops4j.pax.logging.PaxLoggingService". One might expect that this is the needed service right away, but it is slightly more complicated: The registered OSGi service is an OSGi service factory, and returns a different object. Luckily, that object is an inner class of org.ops4j.pax.logging.log4j2.internal.PaxLoggingServiceImpl, so the outer instance can be fetched by accessing the hidden "this$0" field via reflection.

We are currently preparing the related code for testing, and if it holds up, we will probably release this in about 1-2 weeks. Then I can add a pointer to actual code here. (We only mirror our code to Github on releases at this time.)

A cleaner solution, of course, would be the pax developers providing an API method that does the same as the internal update() method. Any feedback on whether this makes sense in general is welcome -- if yes, then I'd open a separate issue for it.

@grgrzybek
Copy link
Member

Thanks for describing this clever solution!
I'd have to think about it, but for now I think we should avoid reflective access to this$0 ;)

But do not lose hope - there's #336 issue which aims to implement OSGi CMPN R8 101.4 Logger Configuration

maybe this is the way to get "into" the internals?

@rmischke-dlr
Copy link

The this$0 step is obviously not nice in general -- but do you have any particular reason to avoid it? From what I've read, it seemed to be fairly standardized, even across JVMs. I have only tested it with AdoptOpenJDK so far, though. If that step is unreliable, I'd really like to know, for obvious reasons :)

The LoggerAdmin API looks like a good step in general, but I'm not sure if it would help with this use case. In particular, there is no "reconfigure()" method or similar, only clearing the configuration and setting log levels, unless I'm missing something. These operations are, however, too limited for our use case -- we need to be able to fundamentally reconfigure appenders at runtime.

@grgrzybek
Copy link
Member

Indeed - the best thing would be to get full access to underlying Log4j manager... After I survive this log4j CVE apocalypse I'll provide more comments, ok?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants