diff --git a/build.sbt b/build.sbt index 46ffb1314bae..77b1fde97ee2 100644 --- a/build.sbt +++ b/build.sbt @@ -1098,11 +1098,14 @@ lazy val `logging-service-logback` = project "org.slf4j" % "slf4j-api" % slf4jVersion, "org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided" ), + Compile / javaModuleName := "org.enso.logging.service.logback", Compile / shouldCompileModuleInfoManually := true, Compile / internalModuleDependencies := Seq( (`logging-service` / Compile / exportedModule).value, (`logging-config` / Compile / exportedModule).value ), + Test / shouldCompileModuleInfoManually := true, + Test / javaModuleName := "org.enso.logging.service.logback.test.provider", Test / moduleDependencies ++= scalaLibrary, Test / internalModuleDependencies := Seq( (Compile / exportedModule).value @@ -2914,6 +2917,8 @@ lazy val `runtime-integration-tests` = //(`ydoc-server` / javaModuleName).value, (`runtime-instrument-common` / javaModuleName).value, (`text-buffer` / javaModuleName).value, + (`logging-service-logback` / Test / javaModuleName).value, + "ch.qos.logback.classic", "truffle.tck.tests" ), Test / addReads := { @@ -2930,7 +2935,10 @@ lazy val `runtime-integration-tests` = (`text-buffer` / javaModuleName).value, (`semver` / javaModuleName).value, "truffle.tck.tests", - "org.openide.util.lookup.RELEASE180" + "org.openide.util.lookup.RELEASE180", + "ch.qos.logback.classic", + (`logging-service-logback` / Compile / javaModuleName).value, + (`logging-service-logback` / Test / javaModuleName).value ), testInstrumentsModName -> Seq(runtimeModName) ) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Logging.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Logging.enso index 3b32ce4b7c9d..c543f40a475f 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Logging.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Logging.enso @@ -3,7 +3,7 @@ import project.Data.Text.Text import project.Meta import project.Nothing.Nothing -polyglot java import java.util.logging.Logger +polyglot java import org.slf4j.LoggerFactory ## PRIVATE Log a message. @@ -12,13 +12,13 @@ polyglot java import java.util.logging.Logger Any.log_message : Text -> Log_Level -> Any Any.log_message self ~message:Text level:Log_Level=Log_Level.Info = type_name = Meta.get_qualified_type_name self - logger = Logger.getLogger type_name + logger = LoggerFactory.getLogger type_name case level of - Log_Level.Finest -> logger.finest message - Log_Level.Fine -> logger.fine message + Log_Level.Finest -> logger.trace message + Log_Level.Fine -> logger.debug message Log_Level.Info -> logger.info message - Log_Level.Warning -> logger.warning message - Log_Level.Severe -> logger.severe message + Log_Level.Warning -> logger.warn message + Log_Level.Severe -> logger.error message self ## PRIVATE diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/StdLibLogsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/StdLibLogsTest.java new file mode 100644 index 000000000000..c19eb24abdaf --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/StdLibLogsTest.java @@ -0,0 +1,66 @@ +package org.enso.interpreter.test; + +import static org.junit.Assert.*; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import java.util.List; +import org.enso.common.MethodNames; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.logging.service.logback.MemoryAppender; +import org.enso.test.utils.ContextUtils; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +public class StdLibLogsTest { + + private static Context ctx; + private static Value mod; + private static EnsoContext ensoContext; + + @BeforeClass + public static void initEnsoContext() { + ctx = ContextUtils.createDefaultContext(); + ensoContext = ContextUtils.leakContext(ctx); + mod = + ctx.eval( + "enso", + """ + from Standard.Base import IO + from Standard.Base.Logging import all + + type Foo + + test = + Foo.log_message level=..Warning "I should warn you about something..." + Foo.log_message level=..Info "Should be seen? By default we only show up-to warnings level" + Foo.log_message level=..Severe "Something went really bad!" + """); + } + + @AfterClass + public static void disposeContext() { + ctx.close(); + ctx = null; + ensoContext.shutdown(); + ensoContext = null; + } + + @Test + public void reportLogsInStdLib() { + mod.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "test"); + var context = (LoggerContext) LoggerFactory.getILoggerFactory(); + var logger = context.getLogger(Logger.ROOT_LOGGER_NAME); + var appender = (MemoryAppender) logger.getAppender("memory"); + var events = appender.getEvents().stream().map(ILoggingEvent::getMessage).toList(); + + assertTrue( + events.containsAll( + List.of("I should warn you about something...", "Something went really bad!"))); + } +} diff --git a/engine/runtime-integration-tests/src/test/resources/application-test.conf b/engine/runtime-integration-tests/src/test/resources/application-test.conf index 6f5255389f60..90958d282090 100644 --- a/engine/runtime-integration-tests/src/test/resources/application-test.conf +++ b/engine/runtime-integration-tests/src/test/resources/application-test.conf @@ -14,7 +14,6 @@ logging-service { appenders = [ { name = "memory" - forward-to = console }, { name = "console" @@ -22,5 +21,5 @@ logging-service { } ] default-appender = memory - log-level = "error" + log-level = "warn" } diff --git a/lib/scala/logging-config/src/main/java/org/enso/logging/config/MemoryAppender.java b/lib/scala/logging-config/src/main/java/org/enso/logging/config/MemoryAppender.java index 132210e51326..7564d1a64ac7 100644 --- a/lib/scala/logging-config/src/main/java/org/enso/logging/config/MemoryAppender.java +++ b/lib/scala/logging-config/src/main/java/org/enso/logging/config/MemoryAppender.java @@ -19,8 +19,8 @@ private MemoryAppender(String forwardTo) { } public static MemoryAppender parse(Config config) { - String fowardTo = config.hasPath(forwardToKey) ? config.getString(forwardToKey) : "console"; - return new MemoryAppender(fowardTo); + String forwardTo = config.hasPath(forwardToKey) ? config.getString(forwardToKey) : ""; + return new MemoryAppender(forwardTo); } @Override @@ -49,5 +49,14 @@ public String getName() { return appenderName; } + @Override + public String toString() { + if (this.forwardTo != null && !this.forwardTo.equals("")) { + return "MemoryAppender[forwardTo=" + forwardTo + "]"; + } else { + return "MemoryAppender[forwardTo=]"; + } + } + private static final String forwardToKey = "forward-to"; } diff --git a/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/LogbackSetup.java b/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/LogbackSetup.java index 3bfa08be31fc..7fe48e544b64 100644 --- a/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/LogbackSetup.java +++ b/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/LogbackSetup.java @@ -256,11 +256,10 @@ public boolean setupMemoryAppender(Level logLevel) { default: target = null; } - if (target == null) { - throw new RuntimeException("unsupported appender " + appenderConfig.getTarget()); + if (target != null) { + target.setContext(env.ctx); + target.start(); } - target.setContext(env.ctx); - target.start(); var memoryAppender = new MemoryAppender(target); env.finalizeAppender(memoryAppender); return true; diff --git a/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/MemoryAppender.java b/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/MemoryAppender.java index f4660812137c..23193f953f02 100644 --- a/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/MemoryAppender.java +++ b/lib/scala/logging-service-logback/src/main/java/org/enso/logging/service/logback/MemoryAppender.java @@ -19,7 +19,7 @@ public class MemoryAppender extends AppenderBase { public MemoryAppender(Appender underlying) { this.underlying = underlying; this.events = new ArrayList<>(); - this.forwardLogs = true; + this.forwardLogs = underlying != null; } protected void append(ILoggingEvent e) { @@ -50,10 +50,23 @@ public void stopForwarding() { this.underlying.stop(); } + public List getEvents() { + return events; + } + @Override public String getName() { return NAME; } + @Override + public String toString() { + if (this.underlying != null) { + return "MemoryAppender[forwardTo=" + this.underlying.getName() + "]"; + } else { + return "MemoryAppender[forwardTo=]"; + } + } + public static final String NAME = "memory"; }