Re: New API for log level manipulation

2024-11-02 Thread Ralph Goers



> On Nov 2, 2024, at 3:51 PM, Piotr P. Karwasz  
> wrote:
> 
> This would be the same setting as in Commons Logging, so I guess I would be 
> OK with that, if we keep an extension mechanism in the API. We could probably 
> split the implementation in two parts: Log4j Core can receive his 
> implementation, while Logback and JUL will be integrated in an internal 
> package of the API (so we can remove them later).
> 
> Once we smooth the API (naming, naming and again naming ;-) ), I can ping 
> Ceki and see if he is willing to adopt it in Logback. Potentially there are a 
> lot of places, where the API could replace logging implementation specific 
> code ([1] and [2]). I pretty much doubt that those projects have both an 
> implementation for Log4j Core and Logback.

I think you missed my point. I don’t think Log4j-core, Logback or whatever 
should need to implement anything. The point of such an API is to provide a 
standard API that implements whatever is necessary to perform the action. i.e. 
in Log4j’s case setLEvel would call Configurator.setLevel.

Ralph

Re: New API for log level manipulation

2024-11-02 Thread Piotr P. Karwasz

Hi Ralph,

On 2.11.2024 22:48, Ralph Goers wrote:

1. getLoggerContext returns a meaningless object. The object returned only has 
value if you know what it is and if you do then you might as well be tied to 
whatever the implementation is.
2. You are passing in an arbitrary parameter to getInstance(). In reality you 
would have to know what the object should be for the implementation you are 
using.


These two methods are part of the "locking" mechanism and they could 
certainly be refactored in a more meaningful way.


The object passed to `getInstance` can be any Java object. Its purpose 
is only to prevent access to the API to all subsequent callers that do 
not own the object. An example of usage:


private static final Object LOGGING_ADMIN_TOKEN = new Object();

private final LoggingConfigurationAdmin = 
LoggingConfigurationAdmin.getInstance(LOGGING_ADMIN_TOKEN);


The `getLoggerContext` method is only used internally, so that 
implementations can tell which "logger context" has been locked. 
Internally there is a map "logger context -> security token" that is 
used to prevent unauthorized access.À priori I assumed that in a 
multi-user environment, each application can configure its own logging 
subsystem.



3. The only thing of real value you are getting out of this are the “Level” 
methods.

Yes, this is the main purpose of the API.

I would think this would have to live in its own repo. It should be able to 
support Logback, Log4j-Core, and JuL simply by checking which is present. In 
other words, the API and the implementation would all reside together in one 
jar. I know you hate doing that but anything else is overkill iMO.


This would be the same setting as in Commons Logging, so I guess I would 
be OK with that, if we keep an extension mechanism in the API. We could 
probably split the implementation in two parts: Log4j Core can receive 
his implementation, while Logback and JUL will be integrated in an 
internal package of the API (so we can remove them later).


Once we smooth the API (naming, naming and again naming ;-) ), I can 
ping Ceki and see if he is willing to adopt it in Logback. Potentially 
there are a lot of places, where the API could replace logging 
implementation specific code ([1] and [2]). I pretty much doubt that 
those projects have both an implementation for Log4j Core and Logback.


Piotr

[1] https://github.com/search?q=LogManager.getContext%28false%29&type=code

[2] 
https://github.com/search?q=LoggerFactory.getILoggerFactory%28%29&type=code





Re: New API for log level manipulation

2024-11-02 Thread Piotr P. Karwasz

Hi Gary,

On 2.11.2024 23:14, Gary D. Gregory wrote:

In general, talking about API signatures without (pseudo)-Javadoc is not great, 
there is too much wrong for miscommunication or plain old guesing.
FWIW, the JavaDoc is there in my repo[1] together with a short 
README[2]. I only removed it to shorten my post to `dev@logging`.


[1] 
https://github.com/ppkarwasz/logging-admin/blob/main/api/src/main/java/org/apache/logging/admin/LoggingConfigurationAdmin.java


[2] https://github.com/ppkarwasz/logging-admin/blob/main/README.adoc


      static LoggingConfigurationAdmin getInstance(Object token,
ClassLoader classLoader);
      static LoggingConfigurationAdmin getInstance(Object token);

Why do I need those AND getLoggerContext()?

I though the point of this interface was a one-stop-shop. What's 
LoggingConfigurationAdmin  doing for me?

...

2. How do we prevent users from abusing this API?

You don't. Or, you don't deliver the JAR with your app. You can't stop users 
from hacking, formally or informally. Reflection is always around the corner to 
boot.


The `token` parameter of `getInstance` is my attempt to limit the abuse 
of the API, by limiting the access to each logger context to the code 
that has access to `token`. This is currently done on a per-logger 
context level, which might explain the `getLoggerContext` method (used 
internally).


Sure, we can not count on a bullet proof mechanism that prevents 
multiple entities from modifying the logger configuration, but we could 
develop a mechanism of discretionary access control. Currently Spring 
Boot modifies the logging configuration even if it is running in a 
Servlet Container with a single Logger Context. We could provide some 
methods that inform Spring Boot of this fact.



4. What should be the lifecycle of this API and where should it live?

KISS 101: Not ANOTHER repo and version numbering system. Match Log4j and be 
done with it. Unless... you want to make this a new component as a sibling to 
Apache Logging Services Log4j: Apache Logging Services Admin.


I guess I want to make this a sibling project.

Once I have integrated all the feedback you have given into the draft, I 
can create a `logging-admin` repo and we can discuss the details in PRs.


Piotr


Re: New API for log level manipulation

2024-11-02 Thread Piotr P. Karwasz

Hi all,

On 31.10.2024 16:11, Piotr P. Karwasz wrote:
Currently we have `o.a.l.l.c.config.Configurator` that allows level 
manipulation, but this is a Log4j Core specific class, which only 
works with Log4j Core. We could publish a small API (e.g. called 
LogAdmin) that allows to:


* list the configured level of all loggers,

* get the configured level of a single logger,

* set the configured level of a single logger.

I have attempted a first sketch of the Apache Logging Admin API in my 
personal repo[1], which ended up having the following methods (the 
Javadoc is in the repo):


public interface LoggingConfigurationAdmin {
    Object getLoggerContext();
    Set getSupportedLevels();
    Map> getLoggerLevels();
    Optional getLoggerLevel(String loggerName);
    void setLoggerLevel(String loggerName, @Nullable String level);
    static LoggingConfigurationAdmin getInstance(Object token, 
ClassLoader classLoader);

    static LoggingConfigurationAdmin getInstance(Object token);
}

While the implementation is rather straightforward, there are some 
aspects we should think about:


1. How should this API be called? I think that the name should NOT 
contain "Log4j", which would cause the same confusion as with Log4j API. 
Users would assume that the API only works with Log4j Core.


2. How do we prevent users from abusing this API? I call "abuse" the 
kind of help some libraries provide to application developers, by 
"improving" the logging configuration behind the application developer's 
back. As an attempt to solve this problem I added a "security token" to 
the `getInstance` method. It works like the token used in Tomcat's JNDI 
implementation[2]: the first caller chooses the token, all subsequent 
calls to `getInstance` must provide the same token.


3. Should we provide some parameters (in the example above 
`ClassLoader`) to help implementations choose the correct logger context 
to modify? Only the Log4j API offers such a parameter to retrieve the 
appropriate `LoggerContext` and in practice the parameter is only used 
by `ClassLoaderContextSelector`, which usually infers the value of the 
parameter anyway.


4. What should be the lifecycle of this API and where should it live? I 
would prefer to keep it in a separate repo, with a separate lifecycle 
(start with version `0.1.0`, so we can make breaking changes in the 
incubating phase) and possibly use a different Maven `groupId` (e.g. 
`org.apache.logging.admin`).


5. Where should the implementations of this API live? It would be nice 
to add implementations of this API directly to the logging 
implementation artifacts (Log4j Core and Logback), but there is a JPMS 
catch: if a JPMS module exports a service, the dependency that defines 
the service type can NOT be optional! Therefore Log4j Core (and maybe 
Logback) would need to have a hard dependency on this API.


What do you think?

Piotr

[1] https://github.com/ppkarwasz/logging-admin

[2] 
https://tomcat.apache.org/tomcat-11.0-doc/api/org/apache/naming/ContextBindings.html





Re: New API for log level manipulation

2024-11-02 Thread Gary D. Gregory
Hi Piotr,

In general, talking about API signatures without (pseudo)-Javadoc is not great, 
there is too much wrong for miscommunication or plain old guesing.

>      Set getSupportedLevels();

It is not helpful to return a set IMO . This should be a list in a documented 
order from one min or max level of specificity to the other end.

>      Object getLoggerContext();

Returning Object is not helpful but I don't know how to solve that or if the 
API is needed at all.

I'm not a fan of Optional in general FWIW.

> Optional getLoggerLevel(String loggerName);
> void setLoggerLevel(String loggerName, @Nullable String level);

Since you can only set the level on a Logger, using "Logger" in the API names 
is superfluous.

>      static LoggingConfigurationAdmin getInstance(Object token, 
> ClassLoader classLoader);
>      static LoggingConfigurationAdmin getInstance(Object token);

Why do I need those AND getLoggerContext()?

I though the point of this interface was a one-stop-shop. What's 
LoggingConfigurationAdmin  doing for me?

> 1. How should this API be called? I think that the name should NOT 
> contain "Log4j", which would cause the same confusion as with Log4j API. 
> Users would assume that the API only works with Log4j Core.

Do you mean the Maven artifact ID? How about "logging-admin"?

> 2. How do we prevent users from abusing this API?

You don't. Or, you don't deliver the JAR with your app. You can't stop users 
from hacking, formally or informally. Reflection is always around the corner to 
boot.

> 4. What should be the lifecycle of this API and where should it live?

KISS 101: Not ANOTHER repo and version numbering system. Match Log4j and be 
done with it. Unless... you want to make this a new component as a sibling to 
Apache Logging Services Log4j: Apache Logging Services Admin.

HTH,
Gary

On 2024/11/02 19:42:15 "Piotr P. Karwasz" wrote:
> Hi all,
> 
> On 31.10.2024 16:11, Piotr P. Karwasz wrote:
> > Currently we have `o.a.l.l.c.config.Configurator` that allows level 
> > manipulation, but this is a Log4j Core specific class, which only 
> > works with Log4j Core. We could publish a small API (e.g. called 
> > LogAdmin) that allows to:
> >
> > * list the configured level of all loggers,
> >
> > * get the configured level of a single logger,
> >
> > * set the configured level of a single logger.
> >
> I have attempted a first sketch of the Apache Logging Admin API in my 
> personal repo[1], which ended up having the following methods (the 
> Javadoc is in the repo):
> 
> public interface LoggingConfigurationAdmin {
>      Object getLoggerContext();
>      Set getSupportedLevels();
>      Map> getLoggerLevels();
>      Optional getLoggerLevel(String loggerName);
>      void setLoggerLevel(String loggerName, @Nullable String level);
>      static LoggingConfigurationAdmin getInstance(Object token, 
> ClassLoader classLoader);
>      static LoggingConfigurationAdmin getInstance(Object token);
> }
> 
> While the implementation is rather straightforward, there are some 
> aspects we should think about:
> 
> 1. How should this API be called? I think that the name should NOT 
> contain "Log4j", which would cause the same confusion as with Log4j API. 
> Users would assume that the API only works with Log4j Core.
> 
> 2. How do we prevent users from abusing this API? I call "abuse" the 
> kind of help some libraries provide to application developers, by 
> "improving" the logging configuration behind the application developer's 
> back. As an attempt to solve this problem I added a "security token" to 
> the `getInstance` method. It works like the token used in Tomcat's JNDI 
> implementation[2]: the first caller chooses the token, all subsequent 
> calls to `getInstance` must provide the same token.
> 
> 3. Should we provide some parameters (in the example above 
> `ClassLoader`) to help implementations choose the correct logger context 
> to modify? Only the Log4j API offers such a parameter to retrieve the 
> appropriate `LoggerContext` and in practice the parameter is only used 
> by `ClassLoaderContextSelector`, which usually infers the value of the 
> parameter anyway.
> 
> 4. What should be the lifecycle of this API and where should it live? I 
> would prefer to keep it in a separate repo, with a separate lifecycle 
> (start with version `0.1.0`, so we can make breaking changes in the 
> incubating phase) and possibly use a different Maven `groupId` (e.g. 
> `org.apache.logging.admin`).
> 
> 5. Where should the implementations of this API live? It would be nice 
> to add implementations of this API directly to the logging 
> implementation artifacts (Log4j Core and Logback), but there is a JPMS 
> catch: if a JPMS module exports a service, the dependency that defines 
> the service type can NOT be optional! Therefore Log4j Core (and maybe 
> Logback) would need to have a hard dependency on this API.
> 
> What do you think?
> 
> Piotr
> 
> [1] https://github.com/ppkarwasz/logging-admin
> 
> [2

Re: New API for log level manipulation

2024-11-02 Thread Ralph Goers
To be honest, I have never been a fan of this kind of interface because:

1. getLoggerContext returns a meaningless object. The object returned only has 
value if you know what it is and if you do then you might as well be tied to 
whatever the implementation is.
2. You are passing in an arbitrary parameter to getInstance(). In reality you 
would have to know what the object should be for the implementation you are 
using. 
3. The only thing of real value you are getting out of this are the “Level” 
methods.

I would think this would have to live in its own repo. It should be able to 
support Logback, Log4j-Core, and JuL simply by checking which is present. In 
other words, the API and the implementation would all reside together in one 
jar. I know you hate doing that but anything else is overkill iMO.

Ralph

> On Nov 2, 2024, at 12:42 PM, Piotr P. Karwasz  
> wrote:
> 
> Hi all,
> 
> On 31.10.2024 16:11, Piotr P. Karwasz wrote:
>> Currently we have `o.a.l.l.c.config.Configurator` that allows level 
>> manipulation, but this is a Log4j Core specific class, which only works with 
>> Log4j Core. We could publish a small API (e.g. called LogAdmin) that allows 
>> to:
>> 
>> * list the configured level of all loggers,
>> 
>> * get the configured level of a single logger,
>> 
>> * set the configured level of a single logger.
>> 
> I have attempted a first sketch of the Apache Logging Admin API in my 
> personal repo[1], which ended up having the following methods (the Javadoc is 
> in the repo):
> 
> public interface LoggingConfigurationAdmin {
> Object getLoggerContext();
> Set getSupportedLevels();
> Map> getLoggerLevels();
> Optional getLoggerLevel(String loggerName);
> void setLoggerLevel(String loggerName, @Nullable String level);
> static LoggingConfigurationAdmin getInstance(Object token, ClassLoader 
> classLoader);
> static LoggingConfigurationAdmin getInstance(Object token);
> }
> 
> While the implementation is rather straightforward, there are some aspects we 
> should think about:
> 
> 1. How should this API be called? I think that the name should NOT contain 
> "Log4j", which would cause the same confusion as with Log4j API. Users would 
> assume that the API only works with Log4j Core.
> 
> 2. How do we prevent users from abusing this API? I call "abuse" the kind of 
> help some libraries provide to application developers, by "improving" the 
> logging configuration behind the application developer's back. As an attempt 
> to solve this problem I added a "security token" to the `getInstance` method. 
> It works like the token used in Tomcat's JNDI implementation[2]: the first 
> caller chooses the token, all subsequent calls to `getInstance` must provide 
> the same token.
> 
> 3. Should we provide some parameters (in the example above `ClassLoader`) to 
> help implementations choose the correct logger context to modify? Only the 
> Log4j API offers such a parameter to retrieve the appropriate `LoggerContext` 
> and in practice the parameter is only used by `ClassLoaderContextSelector`, 
> which usually infers the value of the parameter anyway.
> 
> 4. What should be the lifecycle of this API and where should it live? I would 
> prefer to keep it in a separate repo, with a separate lifecycle (start with 
> version `0.1.0`, so we can make breaking changes in the incubating phase) and 
> possibly use a different Maven `groupId` (e.g. `org.apache.logging.admin`).
> 
> 5. Where should the implementations of this API live? It would be nice to add 
> implementations of this API directly to the logging implementation artifacts 
> (Log4j Core and Logback), but there is a JPMS catch: if a JPMS module exports 
> a service, the dependency that defines the service type can NOT be optional! 
> Therefore Log4j Core (and maybe Logback) would need to have a hard dependency 
> on this API.
> 
> What do you think?
> 
> Piotr
> 
> [1] https://github.com/ppkarwasz/logging-admin
> 
> [2] 
> https://tomcat.apache.org/tomcat-11.0-doc/api/org/apache/naming/ContextBindings.html
> 
>