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

Actuator loggers list endpoint throws exception on Log4J2 loggers with custom log levels #35227

Closed
miladamery opened this issue May 2, 2023 · 6 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@miladamery
Copy link

We are using Log4j as our logging framework. One of our loggers has custom Log level. When calling actuator /loggers endpoint to get list of all loggers exception raises:
EffectiveLevel must not be null

This error is from LoggerConfiguration class constructor which doesnt let null values on effectiveLevel variable:

public LoggerConfiguration(String name, LogLevel configuredLevel, LogLevel effectiveLevel) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(effectiveLevel, "EffectiveLevel must not be null");
		this.name = name;
		this.configuredLevel = configuredLevel;
		this.effectiveLevel = effectiveLevel;
	}

but the real problem comes when calling this class constructor. in Log4J2LoggingSystem.convertLoggerConfig:

private LoggerConfiguration convertLoggerConfig(String name, LoggerConfig loggerConfig) {
		if (loggerConfig == null) {
			return null;
		}
		LogLevel level = LEVELS.convertNativeToSystem(loggerConfig.getLevel());
		if (!StringUtils.hasLength(name) || LogManager.ROOT_LOGGER_NAME.equals(name)) {
			name = ROOT_LOGGER_NAME;
		}
		boolean isLoggerConfigured = loggerConfig.getName().equals(name);
		LogLevel configuredLevel = (isLoggerConfigured) ? level : null;
		return new LoggerConfiguration(name, configuredLevel, level);
	}

The LEVELS variable:

private static final LogLevels<Level> LEVELS = new LogLevels<>();

	static {
		LEVELS.map(LogLevel.TRACE, Level.TRACE);
		LEVELS.map(LogLevel.DEBUG, Level.DEBUG);
		LEVELS.map(LogLevel.INFO, Level.INFO);
		LEVELS.map(LogLevel.WARN, Level.WARN);
		LEVELS.map(LogLevel.ERROR, Level.ERROR);
		LEVELS.map(LogLevel.FATAL, Level.FATAL);
		LEVELS.map(LogLevel.OFF, Level.OFF);
	}

is like above. Our custom log level doesn't exist in this Map. so this line returns null

LogLevel level = LEVELS.convertNativeToSystem(loggerConfig.getLevel());

and we get the exception.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 2, 2023
@wilkinsona
Copy link
Member

Thanks for the report. I wasn't aware that Log4j2 supported custom log levels. As you have noticed, the problem isn't specific to the actuator endpoint. Setting logging.level properties also won't work with a custom level as the values must be one of the levels defined by org.springframework.boot.logging.LogLevel.

We can consider adding support for custom log levels but it looks like it would be quite invasive and require changes to public API. As such, I'm afraid it's unlikely to happen soon.

We could also consider just tolerating levels that we don't recognise, either by dropping them or by performing an approximate mapping. I'm not sure that either would be useful in practice though.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label May 2, 2023
@miladamery
Copy link
Author

I think its acceptable to lose some framework features by using custom log levels, but completely losing list of loggers feature is sour. my lack of knowledge forbids me of going forward. If there is anything I can help with please tell.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 2, 2023
@wilkinsona
Copy link
Member

This also affects Java Util Logging as it too supports custom levels.

@wilkinsona wilkinsona added the for: team-meeting An issue we'd like to discuss as a team to make progress label May 9, 2023
@philwebb
Copy link
Member

philwebb commented May 9, 2023

@miladamery Out of interest, how do you define your custom log levels? I assume you use org.apache.logging.log4j.Level.forName(String, int), but when do you make this call?

@miladamery
Copy link
Author

miladamery commented May 10, 2023

@philwebb yeah, you can create your custom log level with that method, we can pass that variable to log method of logger.

import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager

val logger = LogManager.getLogger()
val CUSTOM_LEVEL= Level.forName("CUSTOM_LEVEL", 1000)
logger.log(CUSTOM_LEVEL, log)

@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided for: team-meeting An issue we'd like to discuss as a team to make progress labels Jun 14, 2023
@philwebb philwebb added this to the 2.7.x milestone Jun 14, 2023
@wilkinsona
Copy link
Member

We'd like to update 2.7.x to tolerate custom log levels in the actuator endpoint. Whether or not that's possible will depend on the scope of the fix and the need for public API changes.

@philwebb philwebb self-assigned this Jun 14, 2023
@philwebb philwebb changed the title Actuator loggers list endpoint throws exception on loggers with custom log levels Actuator loggers list endpoint throws exception on Log4J2 loggers with custom log levels Jun 14, 2023
@philwebb philwebb modified the milestones: 2.7.x, 2.7.13 Jun 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants