Hi, Maybe I add some technical explanation which might clear things up a little.
Pax-Logging essentially consists of two parts, a frontend that implements different logging APIs (slf4j, OSGi logging service, log4j2, apache commons logging…) and a backend, which is doing the actual logging and which is configured with the karaf logging configuration. There are two backends, one using log4j2 (the default) and one using logback, which means that one of these log frameworks is actually there in the backend, but the classes are usually hidden (and the code that is accessing them will depend on the backend). There are actually three different kinds of code that may interact with loggers: 1. Code that is using one of the logging APIs to write logs. 2. Code that is extending the logger e.g. by a custom extender to write specific log formats that are not supported out of the box 3. Code that does both and may also configure loggers but also extends loggers and writes logs Code of the first type is simple, It should work out of the box. Code of the second type should go into a fragment of the pax-logging backend. The fragment is an extension of the actual backend bundle. It has full access to all backend classes (e.g. log4j2) classes in the fragment are also accessible from the backend (this is important if you have your own extender and want to configure it in the log configuration of the Karaf container). Code of the 3rd type is problematic, and you might have to refactor it. The fragment that is exporting the internal backend classes as Grzegorz mentioned might help you in some cases, but this means that your classes can access the log4j classes, but log4j cannot access your classes (which means that if your code contains an appender, the appender would theoretically work, but log4j cannot instantiate it. If I were you, I would remove the log4j specific code of the second and third type for now (of course you should keep the code that is writing logs in the first place). This means that the logs you are writing may not have the format or the log levels you are intending but this should not impact the general functionality. Once the code is running you can consider log configuration and custom appenders and add them to a fragment (and the container log configuration). Best regards Stephan From: Grzegorz Grzybek <gr.grzy...@gmail.com> Sent: Thursday, 14 March 2024 07:07 To: user@karaf.apache.org Subject: Re: Karaf log4j conflict Hello So, for this fragment, do I simply need to make a fragment containing the extra log4j information, or do I need to extract the code that is using those log4j pieces and put that into a fragment. That seems to be a much taller order. Compared to bolting the necessary log4j.core classes onto the pax bundle so that those classes are then available to everyone from the pax bundles classloader. First - here's a sample bundle fragment (attached to pax-logging-log4j2) that adds custom appender: https://github.com/ops4j/org.ops4j.pax.logging/tree/main/pax-logging-samples/fragment-log4j2 For technical details you have two options (writing without actually checking, but I did it many times): * you create a bundle fragment (with <Fragment-Host>org.ops4j.pax.logging.pax-logging-log4j2</Fragment-Host>) that simply uses all private package from Log4j2, which are included (but not exported) from pax-logging-log4j2. You can implement anything you want, including appenders, layouts, ... * you create a bundle fragment (again, with <Fragment-Host>org.ops4j.pax.logging.pax-logging-log4j2</Fragment-Host>) which DOESN'T include any code, but in it's MANIFEST.MF you export the packages you need (like "org.apache.logging.log4j.core") and then your "caterwaul-connect-core" should be resolved against pax-logging-log4j2 with the attached fragment (because effectively, now pax-logging-log4j2 exports what you need). AND YOU DON'T install any Log4j2 bundles at all (just pax-logging-log4j2) The 2nd approach look (maybe) more clever and I used it to make Jetty 9 bundles work with servlet-api 4 bundle (because a fragment added additional exports faking that servlet api 4 exports version 3 of the packages). I hope this helps. regards Grzegorz Grzybek śr., 13 mar 2024 o 19:00 Will Hartung <willhart...@gmail.com<mailto:willhart...@gmail.com>> napisał(a): On Wed, Mar 13, 2024 at 10:35 AM Jean-Baptiste Onofré <j...@nanthrax.net<mailto:j...@nanthrax.net>> wrote: Hi Will Did you take a look on https://github.com/apache/karaf/tree/main/examples/karaf-log-appender-example ? Generally speaking, the org.apache.logging* packages should be imported in your bundle. The fragment would extend an existing bundle classloader with your classes. Maybe if you share a test case bundle, I can show you how to do this. I'm trying to port an existing code base, originally organized as some Maven modules. I'm treating the individual jars independently, and making them bundles individually. One of the bundles has a Log4j appender class of its own, this is in contrast to the example you posted which seems to be a specific pax appender. There's also some other code. It looks like this: @Override public IELogLevel toIELogLevel(Object rawLogEvent) { String logEventClsName = rawLogEvent.getClass().getName(); switch(logEventClsName) { case "org.apache.log4j.spi.LoggingEvent": LoggingEvent loggingEvent = (LoggingEvent)rawLogEvent; return IELogLevel.valueOf(loggingEvent.getLevel().toString()); case "org.apache.logging.log4j.core.LogEvent": case "org.apache.logging.log4j.core.impl.Log4jLogEvent": LogEvent logEvent = (LogEvent)rawLogEvent; return IELogLevel.valueOf(logEvent.getLevel().getStandardLevel().toString()); default: System.out.printf("Unrecognized log event class flavor '%s'. Returning INFO%n", logEventClsName); return IELogLevel.INFO; } } This is not my code, as in I'm not intimately familiar with it at this level, I'm trying to just get it all bundled up to run in an OSGI container. I honestly don't know what calls this at the moment. Then come back to make some passes with declarative services and things like that. But out the gate, just trying to get the thing firing on a few cylinders. So, I'm not ready to try and break code out if I don't have to, if I can get by with classpath/bundlepath shenanigans to get the baseline running. Can a fragment solve this? It seems to me a fragment extends the classloader of another bundle. It inserts itself into another bundles internal environment. In that, should it be trying to export the log4j classes from the pax bundle (which i don't even know if it has these classes internally, I don't know how pax logging works)? Just not sure what the role a fragment might fill or how that would work at this juncture. Thanks again. Regards, Will Hartung