ops4j / org.ops4j.pax.logging

The OSGi Logging framework implementation. Supports SLF4J,LOG4J,JCL etc.
https://ops4j1.jira.com/wiki/spaces/paxlogging/overview
Apache License 2.0
47 stars 79 forks source link

Manifest of pax-logging-logback has an Import-Package directive for org.slf4j version 1.7 instead of 2 #518

Closed ffays closed 1 year ago

ffays commented 1 year ago

I cloned the tagged version 2.2.2, i.e. git clone --branch logging-2.2.2 https://github.com/ops4j/org.ops4j.pax.logging.git

I noticed that for the pax-logging-logback project has a dependency to slf4j-api version 2.0.6 Cf. parent pom.xml line 247 for <version.org.slf4j>2.0.6</version.org.slf4j> declaration:
Cf. parent pom.xml lines 799-803 for slf4j-api dependency declaration.

However in the META-INF/MANIFEST.MF of the packaged pax-logging-logback-2.2.2.jar has an Import-Package directive for org.slf4j version 1.7 instead of 2

Cf.

Import-Package: javax.naming;resolution:=optional,
 ...
 org.slf4j;provider=paxlogging;version="[1.7,2)", 
 org.slf4j.event;provider=paxlogging;version="[1.7,2)",
 org.slf4j.helpers;provider=paxlogging;version="[1.7,2)",
 org.slf4j.spi;provider=paxlogging;version="[1.7,2)",
 ...

This lead to this Exception:

java.lang.ClassNotFoundException: org.slf4j.spi.LoggingEventAware cannot be found by org.ops4j.pax.logging.pax-logging-logback_2.2.2
    at ch.qos.logback.classic.LoggerContext.<init>(LoggerContext.java:81) ~[?:?]
    at org.ops4j.pax.logging.logback.internal.PaxLoggingServiceImpl.<init>(PaxLoggingServiceImpl.java:174) ~[?:?]
    at org.ops4j.pax.logging.logback.internal.Activator.start(Activator.java:102) ~[?:?]

As org.slf4j.spi.LoggingEventAware class is not part of the latest version 1 (i.e. 1.7.36) of slf4j-api.

Could you please fix the Import-Package directive to refer to require version="[2,3)"?

grgrzybek commented 1 year ago

@ffays thanks for report, but please, tel me where do you see this java.lang.ClassNotFoundException? Is it Karaf? Your own OSGi runtime (based on Felix/Equinox)?

Even today (for #516) I run all the integration tests and everything works fine. pax-logging-api bundle is the one exporting multiple versions of org.slf4j.spi package - including 2.0 and 1.7:

Export-Package: \
 org.slf4j; version=${version.org.slf4j}; provider=paxlogging, \
 org.slf4j; version=1.7.36; provider=paxlogging, \
 org.slf4j; version=1.6.6; provider=paxlogging, \
 org.slf4j; version=1.5.11; provider=paxlogging, \
 org.slf4j; version=1.4.3; provider=paxlogging, \
 org.slf4j.event; version=${version.org.slf4j}; provider=paxlogging, \
 org.slf4j.event; version=1.7.36; provider=paxlogging, \
 org.slf4j.helpers; version=${version.org.slf4j}; provider=paxlogging, \
 org.slf4j.helpers; version=1.7.36; provider=paxlogging, \
 org.slf4j.helpers; version=1.6.6; provider=paxlogging, \
 org.slf4j.helpers; version=1.5.11; provider=paxlogging, \
 org.slf4j.helpers; version=1.4.3; provider=paxlogging, \
 org.slf4j.spi; version=${version.org.slf4j}; provider=paxlogging, \
 org.slf4j.spi; version=1.7.36; provider=paxlogging, \
 org.slf4j.spi; version=1.6.6; provider=paxlogging, \
 org.slf4j.spi; version=1.5.11; provider=paxlogging, \
 org.slf4j.spi; version=1.4.3; provider=paxlogging, \
...

So pax-logging-logback should wire to org.slf4j.spi package not from SLF4J library, but from pax-logging-api.

ffays commented 1 year ago

@grgrzybek Indeed I'm trying to load it into Karaf 4.4.3 using Equinox as OSGi runtime.

Starting from a vanilla Karaf 4.4.3 (with data folder deleted):

bundle:install -s -l 80 mvn:org.ow2.asm/asm/9.4
bundle:install -s -l 80 mvn:org.ow2.asm/asm-tree/9.4
bundle:install -s -l 80 mvn:org.ow2.asm/asm-analysis/9.4
bundle:install -s -l 80 mvn:org.ow2.asm/asm-commons/9.4
bundle:install -s -l 80 mvn:org.ow2.asm/asm-util/9.4
bundle:install -s -l 80 mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/1.3.5
bundle:install -l 80 mvn:org.slf4j/slf4j-api/2.0.7
bundle:install -s -l 80 mvn:org.slf4j/slf4j-jdk14/2.0.7
bundle:start slf4j.api
bundle:install -s -l 80 mvn:ch.qos.logback/logback-core/1.3.5
bundle:install -s -l 80 mvn:ch.qos.logback/logback-classic/1.3.5
bundle:install -s -l 80 mvn:org.ops4j.pax.logging/pax-logging-logback/2.2.2

Leads to java.lang.ClassNotFoundException: org.slf4j.spi.LoggingEventAware cannot be found by org.ops4j.pax.logging.pax-logging-logback_2.2.2

I find a bit odd that the org.slf4j.spi package is somewhat "hijacked" with an Export-Package directive from another bundle than slf4j-api. Keep in mind in such situation, regarding to OSGi definition, the package implementation of both plugins exporting it are supposed to be equivalent, therefore Equinox can pick either the first or the second bundle ...

grgrzybek commented 1 year ago

@ffays Karaf 4.4.2 by itself uses pax-logging-api + pax-logging-log4j2. If you want Logback, you have to build your own custom Karaf distro using framework-logback feature: https://github.com/apache/karaf/blob/karaf-4.4.2/assemblies/features/framework/src/main/feature/feature.xml#L51-L74:

    <feature version="${project.version}" description="Karaf core feature" name="framework-logback" hidden="true">
        <!-- persistent wiring extension -->
        <bundle start-level="1">mvn:org.apache.karaf.features/org.apache.karaf.features.extension/${project.version}</bundle>
        <!-- mvn: url handlers -->
        <bundle start-level="5">mvn:org.ops4j.pax.url/pax-url-aether/${pax.url.version}</bundle>
        <!-- logging -->
        <bundle start-level="8">mvn:org.ops4j.pax.logging/pax-logging-api/${pax.logging.version}</bundle>
        <bundle start-level="8">mvn:org.ops4j.pax.logging/pax-logging-logback/${pax.logging.version}</bundle>
        <!-- config admin -->
        <bundle start-level="9">mvn:org.osgi/org.osgi.util.function/1.2.0</bundle>
        <bundle start-level="9">mvn:org.osgi/org.osgi.util.promise/1.2.0</bundle>
        <bundle start-level="9">mvn:org.apache.felix/org.apache.felix.coordinator/${felix.coordinator.version}</bundle>
        <bundle start-level="9">mvn:org.apache.felix/org.apache.felix.converter/${felix.converter.version}</bundle>
        <bundle start-level="10">mvn:org.apache.felix/org.apache.felix.configadmin/${felix.configadmin.version}</bundle>
        <bundle start-level="11">mvn:org.apache.felix/org.apache.felix.configadmin.plugin.interpolation/${felix.configadmin.interpolation.plugin.version}</bundle>
        <bundle start-level="11">mvn:org.apache.felix/org.apache.felix.cm.json/${felix.cm.json.version}</bundle>
        <bundle start-level="11">mvn:org.apache.sling/org.apache.sling.commons.johnzon/${sling.commons.johnzon.version}</bundle>
        <bundle start-level="11">mvn:org.apache.felix/org.apache.felix.configurator/${felix.configurator.version}</bundle>
        <bundle start-level="11">mvn:org.apache.karaf.config/org.apache.karaf.config.core/${project.version}</bundle>
        <!-- file install -->
        <bundle start-level="12">mvn:org.apache.felix/org.apache.felix.fileinstall/${felix.fileinstall.version}</bundle>
        <!-- features service -->
        <bundle start-level="15">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
    </feature>

I find a bit odd that the org.slf4j.spi package is somewhat "hijacked" with an Export-Package directive from another bundle than slf4j-api.

See https://github.com/ops4j/org.ops4j.pax.logging/blame/b7f13ea5b6ac5481da7e203cf3b532d3fdef0c6f/api/osgi.bundle - it was added in 2007 with this commit: https://github.com/ops4j/org.ops4j.pax.logging/commit/528cf5d2ddfc85c3bb2647e1a1e63c3c795bd3ba ;)

I agree - but that's how it works and that's the implementation detail chosen in the golden age of OSGi...

ffays commented 1 year ago

@grgrzybek I've to admit I'm getting a bit lost ... as I'm initial intent is to have the "vanilla" java.util.logging (JUL) package to work within Karaf, and so far I have no success to have logging messages showing below the INFO level (i.e. FINEST, FINER and FINE are not showing), so I try to understand what to do with OPS4J Pax Logging to have lower level JUL messages going thru Karaf logging.

Somewhat I'm glad that your are on this message thread, as you were in charge of the JUL Levels test for Logback (cf. commit d0e66267ee7d066b2b3e11ad68a6400bf3a04f2e)

Nowadays org.ops4j.pax.logging.logback.internal.PaxLoggingServiceImpl has this comment:

To sync java.util.logging logger levels with Logback logger levels, be sure to include this in your logback.xml:
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>

However "Logback" is not part of the vanilla installation of Karaf, so I had the idea i've somewhat to deploy it to have access to this configuration ... maybe I'm wrong.

The bottom line I would like to have JUL working and to see my development "FINE" log messages ... be welcomed to provide guidance/advice to have it working!

PS. Regarding your comment: "I agree - but that's how it works and that's the implementation detail chosen in the golden age of OSGi..." ... If you believe things can be improved/fixed, I encourage you to do so!

grgrzybek commented 1 year ago

@ffays I can understand the confusion.

You have to remember few things about the internal, unavoidable and inherent structure of Pax Logging - there are two layers of logging here:

  1. facade / API
  2. backend / implementation

We used to have 3 implementations - Log4j1, Log4j2 and Logback, now we got rid of Log4j1. However we still have many APIs / facades:

And these are also APIs - even if they're also implementations:

And finally, Logback doesn't have any special API - it's recommended to be used behind SLF4J.

Now, the main principle of Pax Logging was to allow many bundles/libraries, running within OSGi environment (like Karaf) to use any kind of logging API, while ALL the log methods should be directed to single logging implementation, configured using single configuration file.

So, in my opinion the most popular API is SLF4J and I write my libraries/bundles to use this API. But in OSGi runtime, I want the logging to be performed by Log4j2. This is quite easy and common scenario. Outside of OSGi it's realized by:

But imagine this - a bundle is using Log4j1 API and you still want to have actual logging to be performed by Log4j2 - that's what Pax Logging is for. Same for Commons Logging, JBoss Logging etc.

Check out this test: https://github.com/ops4j/org.ops4j.pax.logging/blob/main/pax-logging-it/src/test/java/org/ops4j/pax/logging/it/AllLoggingFacadesIntegrationTest.java:

        String name = "org.ops4j.pax.logging.it.test";

        // 1. SLF4j
        org.slf4j.LoggerFactory.getLogger(name).info("INFO using SLF4J");
        // 2. Commons Logging
        org.apache.commons.logging.LogFactory.getLog(name).info("INFO using Commons Logging");
        // 3. JULI Logging
        org.apache.juli.logging.LogFactory.getLog(name).info("INFO using Juli Logging");
        // 4. Avalon Logging
        org.ops4j.pax.logging.avalon.AvalonLogFactory.getLogger(name).info("INFO using Avalon Logging");
        // 5. JBoss Logging
        org.jboss.logging.Logger.getLogger(name).info("INFO using JBoss Logging");
        // 6. Log4J1 API
        org.apache.log4j.Logger.getLogger(name).info("INFO using Log4Jv1");
        // 7. Logback - only behind SLF4J
        // 8. Log4J2
        // Log4J2 Logging involves log() methods that pass FQCN
        org.apache.logging.log4j.LogManager.getLogger(name).info("INFO using Log4Jv2");
        // 9. JUL - extra handling without a pax-logging specific facade and shadowing. Only handler redirection
        java.util.logging.Logger.getLogger(name).info("INFO using java.util.logging");
        java.util.logging.Logger.getLogger(name).fine("FINE using java.util.logging");
        java.util.logging.Logger.getLogger(name).finer("FINER using java.util.logging");
        java.util.logging.Logger.getLogger(name).finest("FINEST using java.util.logging");

All the above calls are handled by the same logging implementation!

Now you have to realize the magic behind pax-logging-api bundle - indeed it exports org.slf4 package, so your:

org.slf4j.LoggerFactory.getLogger(name).info("INFO using SLF4J");

Uses:

classes not from real org.slf4j/slf4j-api jar/bundle, but from pax-logging-api. Why? Because Pax Logging API changes implementation of the facade, so the calls are redirected to underlying OSGi machinery (it's not only about loggers, but also about MDC for example).

The same is for other facades - the facades should be kind of grabbed from real libraries, but implementation should delegate to OSGi (trackers, listeners, ...).

In your case you used pax-logging-logback without pax-logging-api - but with org.slf4j/slf4j-api library. But this official library doesn't know much about which implementation to use, so it can do only what is done in flat-classpath scenario:

But in OSGi the discovery is more dynamic, so pax-logging-api version (for SLF4J 1.x) provided own implementation of org.slf4j.impl.StaticLoggerBinder with service tracking etc and for SLF4J 2.x it provides own org.ops4j.pax.logging.slf4j.PaxLoggingSLF4JServiceProvider.

And finally an explanation of your problem with java.util.logging - pax-logging-api (in org.ops4j.pax.logging.internal.Activator) calls:

java.util.logging.Logger.addHandler(new org.ops4j.pax.logging.internal.JdkHandler());

So everything again can be handled by single chosen logging backend. Standard Karaf distro uses pax-logging-log4j2, but if you build your own Karaf distro with framework-logback framework feature, you'll get pax-logging-api + pax-logging-logback.

I hope this explains the philosophy behind Pax Logging.

Welcome to the OSGi rabbit hole ;)

ffays commented 1 year ago

@grgrzybek Thank you for your detailed explanation

  1. So to get back to my initial issue statement, I still believe there is an issue in the Import-Package directive pointing to package org.slf4j version 1.7 instead of version 2. The rationale is that both pax-logging-api and the slf4j-api bundles are OSGi providers for both packages "org.slf4j" and "org.slf4j.spi" and therefore they should be 100% interoperable (i.e. it is to the packager to decide which flavor of the package implementation to package with the application). As slf4j-api does not provide "org.slf4j.spi.LoggingEventAware" before version 2 then the Import-Package directive has to be updated accordingly.

1.1. To go further, since Oracle has put in place the modularization in Java 9, I'm concerned that this library publishes classes in package names belonging to another open source project. Looking into "pax-logging-api-2.2.2.jar", I see packages "org.slf4j.", "org.osgi.", "org.jboss." and "org.apache." that are out of the "org.ops4j" package namespace that to my belief should be the only one present. For example the project Apache TomEE has transitioned from package naming javax. (belonging to Java and therefore Oracle) to jakarata.. Keeping these foreign package names is preventing to use the java modularisation, not being able to rely on the Automatic-Module-Name directive. I believe such things should be addressed once and for all, and to no longer happen since Java 9 has been released. (maybe should I open another issue for this!?)

  1. To go back to real initial intent, whereas I would to leverage on java.util.logging for my application

I had already analyzed the code of org.ops4j.pax.logging.internal.Activator and indeed it resets the main LogManager and take over the root java.logger.util.Logger discarting so any configuration that could have been made via the "java.util.logging.config.file" system property unless the "org.ops4j.pax.logging.skipJUL=true" system property is defined.

Still even if "org.ops4j.pax.logging.DefaultServiceLog.level=DEBUG" system property is defined, I cannot see log messages below INFO level for JUL.

Configuring "etc/java.util.logging.properties" seems to be pointless as it does not solve JUL logging below INFO level issue.

I finally figured out that changing "log4j2.rootLogger.level = DEBUG" in "etc/org.ops4j.pax.logging.cfg" allows me to see the messages below INFO level for the OSGi logger but not for the JUL logger ... my quest continue ... (Note that I still wonder why have I to configure the settings for Log4J2 in a configuration file "etc/org.ops4j.pax.logging.cfg" that is not named after Log4J2 !? I would say that's totally counter-intuitive!)

Note that I hear you having the Unit Test passing, and this is certainly a good thing, however my feedback here is about what I do experience in a real deployment environment, so lets say that my experiments with Karaf might lead to have to adjust the Unit Test accordingly!?

So what am I missing so far to have JUL message below INFO level to show in the Karaf log file?

I guess I should open a separate issue this second point it is not the main topic of this issue!?

-/-

My two cents: I would like to emphasize that logging must be a basic commodity for software developers (i.e. it should be simple to use and not be "rocket-sience" grade). I've always been concerned to see all these new logging APIs flourishing in the Java community after the java.util.logging API has been published (that exists since Java 1.4, thus since more than 20 years, and if I'm correct, only Log4J (version 1) predate it of one year...) I understand that software developers must have choices and that somewhat several Java libraries to perform logging should be considered has a benefit. Still if even me as a seasoned Java developer, I struggle to have the "vanilla" java.util.logging library being easily configured in Karaf, I believe there is something to be improved, i.e. the documentation, the implementation or even me!?

ffays commented 1 year ago

I've opened two separate issues for the two later points:

  1. pax-logging-api should not bundle "foreign" Java classes. #519
  2. java.util.logging (JUL) messages below INFO level are not recorded in Karaf logs #520
grgrzybek commented 1 year ago

I'll answer to your concerns tomorrow. Now I can only say that #519 can't be done.

OSGi is great in theory, but painful in practice - 99% of the Maven Central libraries are not OSGi-first and even if they have OSGi-compliant META-INF/MANIFEST.MF it's more like a contribution for other authors or just automatic benefit of using maven-bundle-plugin (which, when used with defaults, sometimes leads to weird artifacts).

The point is that we want to use org.slf4j package - true, that's the promise of OSGi. But we HAVE TO know where this package comes from - and that's the requirement of reality. As I said - pax-logging-api needs to take over org.slf4j package to provide the same interface with different implementation.

Maybe it's better visible with the promise of J2EE/JavaEE/JakartaEE. I've been working with EE since 2002 and while the promise is that you use API, while entire implementation comes from (back in 2002 quite expensive, >10000$ per CPU per year) the underlying application server, the reality check shows that it's simply not possible. You HAVE to know whether you use Hibernate or EclipseLink as your JPA implementation. Same for JMS, JCA, JTA, ... The best separation comes with Servlet API, but still - you have to be aware where do you deploy your WARs to.

With OSGi you're not only adding new layer of dependency management (besides Maven), you wire multiple packages, you deal with tens of Guava implementations differing by major version on each release (thus, according to Semantic Versioning, incompatible), you private package libraries which you don't want as bundles (felix.utils, commons-io, httpclient, ...), you do all the kinds of magic...

So no - there's no way we remove org.slf4j from pax-logging-api bundle. Same for other packages - would you risk your system installing pax-logging-api without org.apache.log4j (yes - Log4j1) package, hoping that official log4j/log4j artifact will work? (yes - it HAS OSGi headers). No way! ;) Have a look at how many different versions of the same packages are exported from pax-logging-api - this is explicit, careful, conscious decision of original Pax Logging authors (I'm only a janitor here ;).

...

More rants and explanations tomorrow ;)

mattrpav commented 1 year ago

Echoing Grzegorz comments – logging is a fundamental capability that application servers must be able to make opinionated decisions in order to support running as many deployment types (and their dependencies) as possible. Karaf is top-of-class in that regard—thanks to pax-logging’s approach.

I wonder if the disconnect here is development vs runtime dependency management.

During development, your project may depend on slf4j-api (provided) or other back-end implementations (test -or- provided).

At deployment, the Karaf runtime provides the logging APIs and Impls, so there is no need to include logging jars in the deployment descriptor. Just like java.lang.String, or other “core” features. The runtime provides those to the deployment.

The practice of including logging jars in wars goes back to practical work-arounds to limitations that those containers (Websphere, Tomcat, etc) had and are not reflective of any true best practice.

My $0.02

-Matt Pavlovich

From: Grzegorz Grzybek @.> Date: Tuesday, March 28, 2023 at 11:38 AM To: ops4j/org.ops4j.pax.logging @.> Cc: Subscribed @.***> Subject: Re: [ops4j/org.ops4j.pax.logging] Manifest of pax-logging-logback has an Import-Package directive for org.slf4j version 1.7 instead of 2 (Issue #518)

I'll answer to your concerns tomorrow. Now I can only say that #519https://github.com/ops4j/org.ops4j.pax.logging/issues/519 can't be done.

OSGi is great in theory, but painful in practice - 99% of the Maven Central libraries are not OSGi-first and even if they have OSGi-compliant META-INF/MANIFEST.MF it more like a contribution for other authors or just automatic benefit of using maven-bundle-plugin (which, when used with defaults, sometimes leads to weird artifacts).

The point is that we want to use org.slf4j package - true, that's the promise of OSGi. But we HAVE TO know where this package comes from - and that's the requirement of reality. As I said - pax-logging-api needs to take over org.slf4j package to provide the same interface with different implementation.

Maybe it's better visible with the promise of J2EE/JavaEE/JakartaEE. I've been working with EE since 2002 and while the promise is that you use API, while entire implementation comes from (back in 2002 quite expensive, >10000$ per CPU per year) the underlying application server, the reality check shows that it's simply not possible. You HAVE to know whether you use Hibernate or EclipseLink as your JPA implementation. Same for JMS, JCA, JTA, ... The best separation comes with Servlet API, but still - you have to be aware where do you deploy your WARs to.

With OSGi you're not only adding new layer of dependency management (besides Maven), you wire mnultiple packages, you deal with tens of Guava implementations differing by major version on each release (thus, according to Semantic Versioninghttps://semver.org/, incompatible), you private package libraries which you don't want as bundles (felix.utils, commons-io, httpclient, ...), you do all the kinds of magic...

So no - there's no way we remove org.slf4j from pax-logging-api bundle. Same for other packages - would you risk your system installing pax-logging-api without org.apache.log4j (yes - Log4j1) package, hoping that official log4j/log4j artifact will work? (yes - it HAS OSGi headers). No way! ;) Have a look at how many different versions of the same packages are exported from pax-logging-api - this is explicit, careful, conscious decision of original Pax Logging authors (I'm only a janitor here ;).

...

More rants and explanations tomorrow ;)

— Reply to this email directly, view it on GitHubhttps://github.com/ops4j/org.ops4j.pax.logging/issues/518#issuecomment-1487259544, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAD5A57W7HYMVYSYHXGQNDLW6MHZDANCNFSM6AAAAAAWJL2AFE. You are receiving this because you are subscribed to this thread.Message ID: @.***>

grgrzybek commented 1 year ago

@grgrzybek Thank you for your detailed explanation

1. So to get back to my initial issue statement, I still believe there is an issue in the Import-Package directive pointing to package org.slf4j version 1.7 instead of version 2.
   The rationale is that both pax-logging-api and the slf4j-api bundles are OSGi providers for both packages "org.slf4j" and  "org.slf4j.spi" and therefore they should be 100% interoperable (i.e. it is to the packager to decide which flavor of the package implementation to package with the application).
   As slf4j-api does not provide "org.slf4j.spi.LoggingEventAware" before version 2 then the Import-Package directive has to be updated accordingly.

You're right here. Even if it's only about the principles and not actually how it works. After switching from Logback 1.2 to 1.3 (which switches from SLF4J 1.7 to 2.0), pax-logging-logback should've indicated this in its Import-Package. Technically, pax-logging-logback would wire to pax-logging-api (even if with [1.7,2.0) version range) and would find org.slf4j.spi.LoggingEventAware class, but this should be more explicit. Also mind that pax-logging-logback does this:

Import-Package: org.slf4j.spi; provider="paxlogging"; version="[1.7,2)"

So we're explicitly stating that we want this package only from a provider with explicit provider="paxlogging" attribute. Yes - that's against the spirit of OSGi where every package is equal. But we know it's not the case.

1.1. To go further, since Oracle has put in place the modularization in Java 9, I'm concerned that this library publishes classes in package names belonging to another open source project. Looking into "pax-logging-api-2.2.2.jar", I see packages "org.slf4j.", "org.osgi.", "org.jboss." and "org.apache." that are out of the "org.ops4j" package namespace that to my belief should be the only one present. For example the project Apache TomEE has transitioned from package naming javax. (belonging to Java and therefore Oracle) to jakarata.. Keeping these foreign package names is preventing to use the java modularisation, not being able to rely on the Automatic-Module-Name directive. I believe such things should be addressed once and for all, and to no longer happen since Java 9 has been released. (maybe should I open another issue for this!?)

Don't make me start about Jigsaw / JPMS / Java modules ;) Did you deal with --patch-module (kind of equivalent of OSGi fragment) or --add-opens? :) JPMS is completely incompatible with OSGi. OSGi is not better - it's completely different. OSGi doesn't deal with modules, only with packages (bundles are only package carriers). Jigsaw deals with modules and packages are modules' "properties". So module first (Jigsaw) vs package first (OSGi). Jigsaw is great in modularizing the JDK itself, but normally you don't focus on the much. With OSGi, you focus on OSGi very much.

So no - "I believe such things should be addressed once and for all, and to no longer happen since Java 9 has been released." - JDK9 was released on 2017-09-21 (5.5 years ago) and I just see customers moving to JDK11 from JDK8. No way OSGi is going to rebuild itself around JPMS...

2. To go back to real initial intent, whereas I would to leverage on java.util.logging for my application

I had already analyzed the code of org.ops4j.pax.logging.internal.Activator and indeed it resets the main LogManager and take over the root java.logger.util.Logger discarting so any configuration that could have been made via the "java.util.logging.config.file" system property unless the "org.ops4j.pax.logging.skipJUL=true" system property is defined.

While java.util.logging.config.file may be read by some static blocks of JUL classes, what's important is the replaced root handler of JUL system. And this handler delegates to Pax Logging implementation which uses org.ops4j.pax.logging Configuration Admin PID. Period.

Still even if "org.ops4j.pax.logging.DefaultServiceLog.level=DEBUG" system property is defined, I cannot see log messages below INFO level for JUL.

This property is used if you have only pax-logging-api bundle installed without installing backend bundle like pax-logging-log4j2 or pax-logging-logback.

Configuring "etc/java.util.logging.properties" seems to be pointless as it does not solve JUL logging below INFO level issue.

True. See above.

I finally figured out that changing "log4j2.rootLogger.level = DEBUG" in "etc/org.ops4j.pax.logging.cfg" allows me to see the messages below INFO level for the OSGi logger but not for the JUL logger ... my quest continue ... (Note that I still wonder why have I to configure the settings for Log4J2 in a configuration file "etc/org.ops4j.pax.logging.cfg" that is not named after Log4J2 !? I would say that's totally counter-intuitive!)

I've show you how to configure level for JUL logger in #520.

And about this configfile name? Again - this is OSGi in practice (opposite to OSGi shouted out from the Ivory Tower). etc/*.cfg files are processed by felix.fileinstall, configured for Karaf in etc/config.properties:

felix.fileinstall.enableConfigSave = true
felix.fileinstall.dir    = ${karaf.etc}
felix.fileinstall.filter = .*\\.(cfg|config|json)
felix.fileinstall.poll   = 1000
felix.fileinstall.noInitialDelay = true
felix.fileinstall.log.level = 3
felix.fileinstall.log.default = jul

This file is taken by felix.fileinstall, PID (Persistent Identifier) is determined (skip the extension, result in org.ops4j.pax.logging PID) and passed to Configuration Admin OSGi service (implemented by felix.configadmin bundle). Configuration Admin service notifies registered org.osgi.service.cm.ManagedService OSGi services (listeners) about such configuration. One of such listeners is registered by pax-logging-log4j2 (or pax-logging-logback) bundles, so Pax Logging actually gets this configuration and does whatever it needs to do.

pax-logging-log4j2 bundle takes the properties prefixed with log4j2. (that's kind of convention from the Log4j1 times, where properties were prefixed with log4j.), strips the prefix and prepares a org.apache.logging.log4j.core.config.Configuration implementation. The rest is specific to Log4j2 itself.

pax-logging-logback (or rather Logback's ch.qos.logback.classic.LoggerContext) can't be configured using properties, so only one property is used - org.ops4j.pax.logging.logback.config.file which points to actual Logback's XML configuration file.

Note that I hear you having the Unit Test passing, and this is certainly a good thing, however my feedback here is about what I do experience in a real deployment environment, so lets say that my experiments with Karaf might lead to have to adjust the Unit Test accordingly!?

So what am I missing so far to have JUL message below INFO level to show in the Karaf log file?

I guess I should open a separate issue this second point it is not the main topic of this issue!?

See #520.

-/-

My two cents: I would like to emphasize that logging must be a basic commodity for software developers (i.e. it should be simple to use and not be "rocket-sience" grade). I've always been concerned to see all these new logging APIs flourishing in the Java community after the java.util.logging API has been published (that exists since Java 1.4, thus since more than 20 years, and if I'm correct, only Log4J (version 1) predate it of one year...) I understand that software developers must have choices and that somewhat several Java libraries to perform logging should be considered has a benefit. Still if even me as a seasoned Java developer, I struggle to have the "vanilla" java.util.logging library being easily configured in Karaf, I believe there is something to be improved, i.e. the documentation, the implementation or even me!?

Your assumption about simple usage is completely rational. However we're talking about OSGi and while I love this technology, it has the highest imaginable actual-difficulty to promised-difficulty ratio... As @mattrpav correctly stated you actually should have this in your POM:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <scope>provided</scope>
</dependency>

Expecting actual library to be available at runtime - exactly as you do with Servlet API Jar - you don't put it into your WAR file!

You're right - JUL was introduced with JDK 1.4, but it doesn't make it the final, ultimate and perfect logging solution ;) The popularity of Logback and Log4j2 which came after JUL suggests the opposite. You should note the discrepancy between Java/JavaEE promise ("you don't have to look at other solutions, stick on our APIs and you'll be fine") and actual situation (popularity of Spring Boot for example). I always preferred to use SLF4J API, because I can quickly "turn it off" by adding slf4j-nop to the classpath instead of setting system properties to specify a JUL file with some weird configuration syntax...

Having said all that, I don't want to close the discussion - feel free to express your concerns, but Pax Logging is what it is - you have to accept the decisions made by giants on whose shoulders I (simple janitor) stand.

ffays commented 1 year ago

Thank your in-depth knowledge over OSGi and Jigsaw.

I've to admit didn't knew the purpose of the provider parameter in the Export-Package directive, so it went out of my radar.

It has been a very instructive discussion, thank you one more time, feel free to close this ticket.

grgrzybek commented 1 year ago

Thanks for inviting me out of my comfort zone - this discussion was very inspiring - my goal was to really admit you have good points, but with OSGi you have to be careful when transitioning from the ideal model to reality ;)