From ca41f2dccff01b22eac17015a1f48920d461edee Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Thu, 1 Feb 2024 14:43:40 +0100 Subject: [PATCH] Logging with Panache: better failure condition When the `Log` API is used inside a Quarkus application, as indicated by presence of `Application.currentApplication()`, all `Log` call sites should be rewritten and hence direct calls to `Log` methods should always fail. Outside of Quarkus, direct calls to `Log` are allowed in tests, as indicated by presence of the JUnit `Assertions` class. --- .../src/main/java/io/quarkus/logging/Log.java | 16 +++++++++---- .../java/io/quarkus/logging/GenerateLog.java | 23 +++++++++++++++---- .../logging/LoggingApiCompletenessTest.java | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/core/runtime/src/main/java/io/quarkus/logging/Log.java b/core/runtime/src/main/java/io/quarkus/logging/Log.java index 135b391c2f79c..3f4f3472e2739 100644 --- a/core/runtime/src/main/java/io/quarkus/logging/Log.java +++ b/core/runtime/src/main/java/io/quarkus/logging/Log.java @@ -2,6 +2,8 @@ import org.jboss.logging.Logger; +import io.quarkus.runtime.Application; + // automatically generated by io.quarkus.logging.GenerateLog /** * Copy of {@link org.jboss.logging.BasicLogger}. @@ -12,14 +14,18 @@ public final class Log { private static final StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - private static final boolean shouldFail = !isTest(); + private static final boolean shouldFail = shouldFail(); - private static boolean isTest() { + private static boolean shouldFail() { + // inside Quarkus, all call sites should be rewritten + if (Application.currentApplication() != null) + return true; + // outside Quarkus, allow in tests try { Class.forName("org.junit.jupiter.api.Assertions"); - return true; - } catch (java.lang.ClassNotFoundException ignored) { return false; + } catch (java.lang.ClassNotFoundException ignored) { + return true; } } @@ -2919,6 +2925,6 @@ public static void logf(String loggerFqcn, Logger.Level level, Throwable t, Stri private static UnsupportedOperationException fail() { return new UnsupportedOperationException( - "Using io.quarkus.logging.Log is only possible with Quarkus bytecode transformation"); + "Using io.quarkus.logging.Log is only possible with Quarkus bytecode transformation; make sure the archive is indexed, for example by including a beans.xml file"); } } diff --git a/core/runtime/src/test/java/io/quarkus/logging/GenerateLog.java b/core/runtime/src/test/java/io/quarkus/logging/GenerateLog.java index b108f58de3d38..b46335055ca64 100644 --- a/core/runtime/src/test/java/io/quarkus/logging/GenerateLog.java +++ b/core/runtime/src/test/java/io/quarkus/logging/GenerateLog.java @@ -29,10 +29,14 @@ import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.CatchClause; +import com.github.javaparser.ast.stmt.IfStmt; import com.github.javaparser.ast.stmt.ReturnStmt; +import com.github.javaparser.ast.stmt.Statement; import com.github.javaparser.ast.stmt.TryStmt; import com.github.javaparser.ast.type.PrimitiveType; +import io.quarkus.runtime.Application; + public class GenerateLog { private static final String CLASS_JAVADOC = "" + "Copy of {@link org.jboss.logging.BasicLogger}.\n" + @@ -69,6 +73,7 @@ private static void generateLogClass(String templateSource) { CompilationUnit unit = new CompilationUnit(); unit.setPackageDeclaration("io.quarkus.logging"); unit.addImport(Logger.class); + unit.addImport(Application.class); unit.addOrphanComment(new LineComment(" automatically generated by io.quarkus.logging.GenerateLog")); ClassOrInterfaceDeclaration clazz = unit.addClass("Log", Modifier.Keyword.PUBLIC, Modifier.Keyword.FINAL) @@ -79,26 +84,33 @@ private static void generateLogClass(String templateSource) { Modifier.Keyword.PRIVATE, Modifier.Keyword.STATIC, Modifier.Keyword.FINAL); clazz.addFieldWithInitializer(PrimitiveType.booleanType(), "shouldFail", - StaticJavaParser.parseExpression("!isTest()"), + StaticJavaParser.parseExpression("shouldFail()"), Modifier.Keyword.PRIVATE, Modifier.Keyword.STATIC, Modifier.Keyword.FINAL); { - MethodDeclaration method = clazz.addMethod("isTest"); + MethodDeclaration method = clazz.addMethod("shouldFail"); method.setPrivate(true); method.setStatic(true); method.setType(PrimitiveType.booleanType()); BlockStmt body = new BlockStmt(); + Expression ifCondition = StaticJavaParser.parseExpression("Application.currentApplication() != null"); + Statement thenPart = StaticJavaParser.parseStatement("return true;"); + + body.addOrphanComment(new LineComment(" inside Quarkus, all call sites should be rewritten")); + body.addStatement(new IfStmt(ifCondition, thenPart, null)); + BlockStmt tryPart = new BlockStmt(); tryPart.addStatement("Class.forName(\"org.junit.jupiter.api.Assertions\");"); - tryPart.addStatement("return true;"); + tryPart.addStatement("return false;"); BlockStmt catchPart = new BlockStmt(); - catchPart.addStatement("return false;"); + catchPart.addStatement("return true;"); CatchClause catchClause = new CatchClause( new Parameter(StaticJavaParser.parseType(ClassNotFoundException.class.getName()), "ignored"), catchPart); + body.addOrphanComment(new LineComment(" outside Quarkus, allow in tests")); body.addStatement(new TryStmt(tryPart, new NodeList<>(catchClause), null)); method.setBody(body); } @@ -133,7 +145,8 @@ private static void generateLogClass(String templateSource) { method.setType(UnsupportedOperationException.class); BlockStmt body = new BlockStmt(); body.addStatement("return new UnsupportedOperationException(\"Using " + Log.class.getName() - + " is only possible with Quarkus bytecode transformation\");"); + + " is only possible with Quarkus bytecode transformation;" + + " make sure the archive is indexed, for example by including a beans.xml file\");"); method.setBody(body); } diff --git a/core/runtime/src/test/java/io/quarkus/logging/LoggingApiCompletenessTest.java b/core/runtime/src/test/java/io/quarkus/logging/LoggingApiCompletenessTest.java index 33673ab52f9c0..8904b356fe290 100644 --- a/core/runtime/src/test/java/io/quarkus/logging/LoggingApiCompletenessTest.java +++ b/core/runtime/src/test/java/io/quarkus/logging/LoggingApiCompletenessTest.java @@ -62,7 +62,7 @@ public void compareWithJbossLogging() { private static boolean isPrivateStaticAdditionalMethod(Method method) { return Modifier.isPrivate(method.getModifiers()) && Modifier.isStatic(method.getModifiers()) - && ("fail".equals(method.getName()) || "isTest".equals(method.getName())); + && ("fail".equals(method.getName()) || "shouldFail".equals(method.getName())); } private static boolean areEquivalent(Method jbossLoggingMethod, Method quarkusLogMethod) {