GitHub user ppkarwasz added a comment to the discussion: Help with migrating 
from log4j to log4j2 (we also use a slf4j -> log4j)

Hi @paladox,

The only supported API for changing log levels at runtime in Log4j Core is 
[`Configurator`](https://logging.apache.org/log4j/2.x/javadoc/log4j-core/org/apache/logging/log4j/core/config/Configurator.html).
 The simplest form is:

```java
Configurator.setLevel(name, newLevel);
```

This works only if **Log4j Core** is the actual implementation of the Log4j 
API. Since that might not always be the case, it’s good practice to guard the 
call:

```java
try {
  Configurator.setLevel(name, newLevel);
} catch (LinkageError | ClassCastException e) {
  // Log4j Core is not available or not the active implementation
}
```

What this does:

1. Retrieves (or creates) a `LoggerConfig` for `name`.
2. Updates its level.
3. Propagates the configuration change to all affected loggers (any logger 
**without** a more specific config inherits this new level).

### About your current code

```java
config.getLoggers().forEach((loggerName, loggerConfig) -> {
  if (!loggerName.isEmpty() && (name == null || loggerName.contains(name))) {
    loggerConfig.setLevel(newLevel);
    stdout.println("Updated Log4j2 LoggerConfig: " + loggerName + " -> " + 
newLevel);
  }
});
ctx.updateLoggers();
```

This approach differs from `Configurator` in two important ways:

1. It does **not** create a new `LoggerConfig` if one doesn’t already exist for 
`name`.
2. It **overrides** the level of all explicitly configured child loggers.

For example, if `foo` has no config but `foo.bar` and `foo.baz` do, then:

* `foo.bar` and `foo.baz` levels will be overridden.
* `foo` itself will remain unchanged (inheriting from root).

### Adjusting whole hierarchies

If you want to update an entire logger hierarchy, `Configurator.setAllLevels` 
is the intended API:

```java
try {
  Configurator.setAllLevels(name, newLevel);
} catch (LinkageError | ClassCastException e) {
  // Log4j Core is not available or not the active implementation
}
```

### Key difference from Log4j 1

This is probably the root cause of your migration issues:

* In **Log4j 1**, the `Logger` object itself held both runtime state and 
configuration, and parent loggers always existed (`foo.bar` implied `foo`).
* In **Log4j 2 Core**, loggers and their configuration are separate (see 
[Architecture](https://logging.apache.org/log4j/2.x/manual/architecture.html)). 
Only:

  * loggers you actually request in code, and
  * configurations explicitly defined in your config file

are created.

So, to affect loggers that don’t have an explicit configuration, you need to 
use the `Configurator` API rather than directly iterating over existing 
`LoggerConfig`s.

> [!NOTE]
> A **Logger Admin API** is planned (see 
> [apache/logging-admin](https://github.com/apache/logging-admin)) to provide a 
> standard, implementation-independent way of managing logger levels. However, 
> development capacity is currently limited, so this is not yet available.


GitHub link: 
https://github.com/apache/logging-log4j2/discussions/3914#discussioncomment-14307854

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to