mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 05:41:32 +03:00
Apply custom log levels to Truffle logger (#8162)
Previously custom log levels applied only to non-Truffle loggers. To allow it, filtering has to be applied appropriately at two places - first at Java's Handler and then essentially re-confirmed at SLF4J's logger to which the former forwards to. Filters compose in an `AND` condition, therefore default log level check had to be merged into our custom filters. `TruffleLogger` has a builtin functionality to perform the filtering when context is configured appropriately. This should be much more efficient than adding a `Filter` to the JUL Handler explicitly. # Important Notes ``` JAVA_OPTS="-org.enso.compiler.SerializationManager.Logger.level=debug" ./built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso --run ``` will now assign a custom log level to `SerializationManager` Logger.
This commit is contained in:
parent
18c7135769
commit
51abb3e1b0
@ -1,12 +1,16 @@
|
||||
package org.enso.runner
|
||||
|
||||
import org.enso.logger.Converter
|
||||
import org.enso.logger.JulHandler
|
||||
import org.enso.logger.{Converter, JulHandler, LoggerSetup}
|
||||
import org.enso.polyglot.debugger.{
|
||||
DebugServerInfo,
|
||||
DebuggerSessionManagerEndpoint
|
||||
}
|
||||
import org.enso.polyglot.{HostAccessFactory, PolyglotContext, RuntimeOptions}
|
||||
import org.enso.polyglot.{
|
||||
HostAccessFactory,
|
||||
LanguageInfo,
|
||||
PolyglotContext,
|
||||
RuntimeOptions
|
||||
}
|
||||
import org.graalvm.polyglot.Engine
|
||||
import org.graalvm.polyglot.Context
|
||||
import org.slf4j.event.Level
|
||||
@ -61,7 +65,8 @@ class ContextFactory {
|
||||
if (javaHome == null) {
|
||||
throw new IllegalStateException("Specify JAVA_HOME environment property");
|
||||
}
|
||||
val logLevelName = Converter.toJavaLevel(logLevel).getName
|
||||
val julLogLevel = Converter.toJavaLevel(logLevel)
|
||||
val logLevelName = julLogLevel.getName
|
||||
val builder = Context
|
||||
.newBuilder()
|
||||
.allowExperimentalOptions(true)
|
||||
@ -101,11 +106,21 @@ class ContextFactory {
|
||||
new DebuggerSessionManagerEndpoint(repl, peer)
|
||||
} else null
|
||||
}
|
||||
.option(
|
||||
RuntimeOptions.LOG_LEVEL,
|
||||
logLevelName
|
||||
)
|
||||
.logHandler(JulHandler.get())
|
||||
|
||||
builder.option(RuntimeOptions.LOG_LEVEL, logLevelName)
|
||||
val logHandler = JulHandler.get()
|
||||
val logLevels = LoggerSetup.get().getConfig.getLoggers
|
||||
if (logLevels.hasEnsoLoggers()) {
|
||||
logLevels.entrySet().forEach { entry =>
|
||||
builder.option(
|
||||
s"log.${LanguageInfo.ID}.${entry.getKey}.level",
|
||||
Converter.toJavaLevel(entry.getValue).getName
|
||||
)
|
||||
}
|
||||
}
|
||||
builder
|
||||
.logHandler(logHandler)
|
||||
|
||||
val graalpy = new File(
|
||||
new File(
|
||||
new File(new File(new File(projectRoot), "polyglot"), "python"),
|
||||
|
@ -55,6 +55,15 @@ public class LoggersLevels {
|
||||
return loggers.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any of the custom levels refer to Enso's loggers.
|
||||
*
|
||||
* @return true if any of the custom log levels are for `org.enso.*` class
|
||||
*/
|
||||
public boolean hasEnsoLoggers() {
|
||||
return loggers.keySet().stream().anyMatch(k -> k.startsWith(ENSO_PKG_PREFIX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read any loggers' levels set via `-Dfoo.bar.Logger.level=<level>` env variables.
|
||||
*
|
||||
@ -94,4 +103,5 @@ public class LoggersLevels {
|
||||
}
|
||||
|
||||
private static String SYS_PROP_SUFFIX = ".Logger.level";
|
||||
private static String ENSO_PKG_PREFIX = "org.enso";
|
||||
}
|
||||
|
@ -9,18 +9,27 @@ import org.enso.logger.config.LoggersLevels;
|
||||
/**
|
||||
* An implementation of ch.qos.logback.core.filter.Filter that is created from configuration's and
|
||||
* user's custom logger levels.
|
||||
*
|
||||
* <p>ApplicationFilter combines custom log levels filter with threshold filter.
|
||||
*/
|
||||
public class ApplicationFilter extends Filter<ILoggingEvent> {
|
||||
private final LoggersLevels loggers;
|
||||
private final Level level;
|
||||
private final String prefix;
|
||||
|
||||
private ApplicationFilter(LoggersLevels loggers) {
|
||||
private final int prefixLength;
|
||||
|
||||
private ApplicationFilter(LoggersLevels loggers, Level level, String prefix) {
|
||||
this.loggers = loggers;
|
||||
this.level = level;
|
||||
this.prefix = prefix;
|
||||
this.prefixLength = prefix != null ? prefix.length() + 1 : 0; // inlude `.` in `enso.`
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterReply decide(ILoggingEvent event) {
|
||||
for (var entry : loggers.entrySet()) {
|
||||
if (event.getLoggerName().startsWith(entry.getKey())) {
|
||||
if (loggerNameMatches(entry.getKey(), event.getLoggerName())) {
|
||||
Level loggerLevel = Level.convertAnSLF4JLevel(entry.getValue());
|
||||
if (event.getLevel().isGreaterOrEqual(loggerLevel)) {
|
||||
return FilterReply.NEUTRAL;
|
||||
@ -29,10 +38,24 @@ public class ApplicationFilter extends Filter<ILoggingEvent> {
|
||||
}
|
||||
}
|
||||
}
|
||||
return FilterReply.NEUTRAL;
|
||||
|
||||
if (event.getLevel().isGreaterOrEqual(level)) {
|
||||
return FilterReply.NEUTRAL;
|
||||
} else {
|
||||
return FilterReply.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
public static Filter<ILoggingEvent> fromLoggers(LoggersLevels loggers) {
|
||||
return new ApplicationFilter(loggers);
|
||||
private boolean loggerNameMatches(String validLoggerName, String eventLoggerName) {
|
||||
if (prefix != null && eventLoggerName.startsWith(prefix)) {
|
||||
return eventLoggerName.substring(prefixLength).startsWith(validLoggerName);
|
||||
} else {
|
||||
return eventLoggerName.startsWith(validLoggerName);
|
||||
}
|
||||
}
|
||||
|
||||
public static Filter<ILoggingEvent> fromLoggers(
|
||||
LoggersLevels loggers, org.slf4j.event.Level level, String prefix) {
|
||||
return new ApplicationFilter(loggers, Level.convertAnSLF4JLevel(level), prefix);
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ public final class LogbackSetup extends LoggerSetup {
|
||||
Filter<ILoggingEvent> filter;
|
||||
LoggersLevels loggers = config != null ? config.getLoggers() : null;
|
||||
if (loggers != null && !loggers.isEmpty()) {
|
||||
filter = ApplicationFilter.fromLoggers(loggers);
|
||||
filter = ApplicationFilter.fromLoggers(loggers, level, LANG_PREFIX);
|
||||
} else {
|
||||
filter = null;
|
||||
}
|
||||
@ -310,11 +310,13 @@ public final class LogbackSetup extends LoggerSetup {
|
||||
encoder.start();
|
||||
}
|
||||
void finalizeAppender(ch.qos.logback.core.Appender<ILoggingEvent> appender) {
|
||||
ThresholdFilter threshold = new ThresholdFilter();
|
||||
threshold.setLevel(ch.qos.logback.classic.Level.convertAnSLF4JLevel(level).toString());
|
||||
appender.addFilter(threshold);
|
||||
threshold.setContext(ctx);
|
||||
threshold.start();
|
||||
if (filter == null) {
|
||||
ThresholdFilter threshold = new ThresholdFilter();
|
||||
threshold.setLevel(ch.qos.logback.classic.Level.convertAnSLF4JLevel(level).toString());
|
||||
appender.addFilter(threshold);
|
||||
threshold.setContext(ctx);
|
||||
threshold.start();
|
||||
}
|
||||
|
||||
// Root's log level is set to the minimal required log level.
|
||||
// Log level is controlled by `ThresholdFilter` instead, allowing is to specify different
|
||||
@ -333,4 +335,6 @@ public final class LogbackSetup extends LoggerSetup {
|
||||
logger.addAppender(appender);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String LANG_PREFIX = "enso";
|
||||
}
|
||||
|
@ -2,10 +2,7 @@ package org.enso.logger;
|
||||
|
||||
import static java.util.logging.Level.*;
|
||||
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import java.util.logging.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user