You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2020/06/08 12:33:08 UTC

[jena] branch master updated: JENA-1912: Fix LogCtl and non-Log4J2 provider. Logging cleanup.

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d8f72d  JENA-1912: Fix LogCtl and non-Log4J2 provider. Logging cleanup.
     new 9363f0a  Merge pull request #753 from afs/logging
5d8f72d is described below

commit 5d8f72debde832f81a6d64cbae28f42f7c087be2
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Fri Jun 5 13:56:39 2020 +0100

    JENA-1912: Fix LogCtl and non-Log4J2 provider. Logging cleanup.
---
 apache-jena/log4j2.properties                      |   6 +
 .../arq/examples/aggregates/CustomAggregate.java   |   2 +-
 .../arq/examples/riot/ExRIOT6_AddNewReader.java    |   2 +-
 .../riot/ExRIOT_RDFXML_ReaderProperties.java       |   2 +-
 .../riot/ExRIOT_RDFXML_WriteProperties.java        |   2 +-
 .../arq/examples/riot/ExRIOTw3_AddNewWriter.java   |   2 +-
 .../examples/update/UpdateExecuteOperations.java   |   2 +-
 .../arq/examples/update/UpdateProgrammatic.java    |   2 +-
 .../arq/examples/update/UpdateReadFromFile.java    |   2 +-
 .../pfunction/library/triple/TripleTermFind.java   |   4 +-
 .../java/org/apache/jena/atlas/logging/LogCmd.java | 135 ++++++++
 .../java/org/apache/jena/atlas/logging/LogCtl.java | 342 ++++++++-------------
 .../java/org/apache/jena/atlas/logging/LogJUL.java | 106 +++++++
 jena-cmds/src/main/java/arq/qexpr.java             |   2 +-
 jena-cmds/src/main/java/arq/rdfdiff.java           |   4 +-
 jena-cmds/src/main/java/jena/RuleMap.java          |   4 +-
 jena-cmds/src/main/java/jena/cmd/CmdMain.java      |   2 +-
 jena-cmds/src/main/java/jena/rdfcat.java           |   7 +-
 jena-cmds/src/main/java/jena/rdfcompare.java       |   6 +-
 jena-cmds/src/main/java/jena/rdfcopy.java          |   4 +-
 jena-cmds/src/main/java/jena/rdfparse.java         |   4 +-
 jena-cmds/src/main/java/jena/schemagen.java        |   4 +-
 jena-cmds/src/main/java/jena/version.java          |   4 +-
 jena-cmds/src/main/java/riotcmd/dumpthrift.java    |   2 +-
 jena-cmds/src/main/java/shacl/shacl.java           |   2 +-
 jena-cmds/src/main/java/shacl/shacl_parse.java     |   2 +-
 jena-cmds/src/main/java/shacl/shacl_validate.java  |   2 +-
 .../main/java/tdb/bulkloader2/CmdIndexBuild.java   |   2 +-
 .../main/java/tdb/bulkloader2/CmdIndexCopy.java    |   2 +-
 .../java/tdb/bulkloader2/CmdNodeTableBuilder.java  |   2 +-
 .../main/java/tdb/bulkloader2/CmdRewriteIndex.java |   2 +-
 jena-cmds/src/main/java/tdb/tools/dumpbpt.java     |   2 +-
 jena-cmds/src/main/java/tdb/tools/dumpjournal.java |   2 +-
 jena-cmds/src/main/java/tdb/tools/dumpnodes.java   |   2 +-
 jena-cmds/src/main/java/tdb2/cmdline/CmdTDB.java   |   2 +-
 jena-cmds/src/test/java/jena/cmd/TS_Cmd.java       |   2 +-
 jena-cmds/src/test/java/shacl/shacl_test.java      |   2 +-
 .../jena/dboe/base/block/TestBlockMgrMapped.java   |   5 -
 .../apache/jena/commonsrdf/TS_JenaCommonsRDF.java  |   9 +-
 .../examples/Ex_JenaGraphToCommonsRDFGraph.java    |   2 +-
 .../examples/Ex_ParseIntoCommonsRDFGraph.java      |   2 +-
 .../apache/jena/fuseki/system/FusekiLogging.java   |  77 +++--
 .../sparqler/log4j2-console.properties             |  12 +-
 .../sparqler/log4j2-file.properties                |  18 +-
 .../jena-fuseki-main/sparqler/run-sparqler         |   6 +-
 .../org/apache/jena/fuseki/main/FusekiServer.java  |   6 +-
 .../jena/fuseki/main/examples/ExampleService.java  |   4 +-
 .../main/examples/ExtendFuseki_AddService_1.java   |   4 +-
 .../main/examples/ExtendFuseki_AddService_2.java   |   4 +-
 .../main/examples/ExtendFuseki_AddService_3.java   |   4 +-
 .../src/test/resources/log4j2.properties           |   2 +-
 .../src/test/java/dboe/BaseSoakTest.java           |   3 -
 .../jena/shacl/examples/Shacl01_validateGraph.java |   2 +-
 .../examples/Shacl02_validateTransaction.java      |   2 +-
 .../jena/tdb/base/block/TestBlockMgrMapped.java    |   5 -
 .../index/bplustree/CmdTestBPlusTreeRewriter.java  |   2 +-
 .../src/main/java/examples/JenaTextExample1.java   |   2 +-
 57 files changed, 515 insertions(+), 334 deletions(-)

diff --git a/apache-jena/log4j2.properties b/apache-jena/log4j2.properties
index c5213b5..761200c 100644
--- a/apache-jena/log4j2.properties
+++ b/apache-jena/log4j2.properties
@@ -13,6 +13,12 @@ appender.console.layout.type = PatternLayout
 appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
 #appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
 
+## appender.file.type = File
+## appender.file.name = OUT
+## appender.file.fileName=log.fuseki
+## appender.file.layout.type=PatternLayout
+## appender.file.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+
 rootLogger.level                  = INFO
 rootLogger.appenderRef.stdout.ref = OUT
 
diff --git a/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java b/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
index 3efb081..3c9f2fe 100644
--- a/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
+++ b/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
@@ -46,7 +46,7 @@ import org.apache.jena.sparql.sse.SSE ;
  * for the "no groups" case.
  */
 public class CustomAggregate {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     /**
      * Execution of a custom aggregate is with accumulators. One accumulator is
      * created for the factory for each group in a query execution.
diff --git a/jena-arq/src-examples/arq/examples/riot/ExRIOT6_AddNewReader.java b/jena-arq/src-examples/arq/examples/riot/ExRIOT6_AddNewReader.java
index 0c24a59..e310583 100644
--- a/jena-arq/src-examples/arq/examples/riot/ExRIOT6_AddNewReader.java
+++ b/jena-arq/src-examples/arq/examples/riot/ExRIOT6_AddNewReader.java
@@ -49,7 +49,7 @@ import org.apache.jena.sparql.util.Context;
 /** Example of using RIOT : register a new input language */
 public class ExRIOT6_AddNewReader
 {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     
     public static void main(String... argv) {
         Lang lang = LangBuilder.create("SSE", "text/x-sse").addFileExtensions("rsse").build();
diff --git a/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_ReaderProperties.java b/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_ReaderProperties.java
index 1ba3245..f87a5d0 100644
--- a/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_ReaderProperties.java
+++ b/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_ReaderProperties.java
@@ -34,7 +34,7 @@ import org.apache.jena.sparql.util.Context;
 
 /** Set proeprties of the RDF/XML parser (ARP) */
 public class ExRIOT_RDFXML_ReaderProperties {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     
     public static void main(String[] args) {
         // Inline illustrative data.
diff --git a/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_WriteProperties.java b/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_WriteProperties.java
index 5e6506a..9668b06 100644
--- a/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_WriteProperties.java
+++ b/jena-arq/src-examples/arq/examples/riot/ExRIOT_RDFXML_WriteProperties.java
@@ -30,7 +30,7 @@ import org.apache.jena.sparql.util.Context;
 
 /** Example of setting properties for RDF/XML writer via RIOT */
 public class ExRIOT_RDFXML_WriteProperties {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
 
     public static void main(String... args) {
         // Data.
diff --git a/jena-arq/src-examples/arq/examples/riot/ExRIOTw3_AddNewWriter.java b/jena-arq/src-examples/arq/examples/riot/ExRIOTw3_AddNewWriter.java
index 5a0abc1..ca1b9c4 100644
--- a/jena-arq/src-examples/arq/examples/riot/ExRIOTw3_AddNewWriter.java
+++ b/jena-arq/src-examples/arq/examples/riot/ExRIOTw3_AddNewWriter.java
@@ -36,7 +36,7 @@ import org.apache.jena.sparql.util.Context ;
 /** Example of registering a new writer with RIOT */
 public class ExRIOTw3_AddNewWriter
 {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     
     // See also ExRIOT6_AddNewLang
     public static void main(String[] args)
diff --git a/jena-arq/src-examples/arq/examples/update/UpdateExecuteOperations.java b/jena-arq/src-examples/arq/examples/update/UpdateExecuteOperations.java
index c2481ed..f7a1975 100644
--- a/jena-arq/src-examples/arq/examples/update/UpdateExecuteOperations.java
+++ b/jena-arq/src-examples/arq/examples/update/UpdateExecuteOperations.java
@@ -35,7 +35,7 @@ import org.apache.jena.update.UpdateRequest ;
 
 public class UpdateExecuteOperations
 {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     public static void main(String []args)
     {
         // Create an empty DatasetGraph (has an empty default graph and no named graphs) 
diff --git a/jena-arq/src-examples/arq/examples/update/UpdateProgrammatic.java b/jena-arq/src-examples/arq/examples/update/UpdateProgrammatic.java
index e62a15c..9c0d331 100644
--- a/jena-arq/src-examples/arq/examples/update/UpdateProgrammatic.java
+++ b/jena-arq/src-examples/arq/examples/update/UpdateProgrammatic.java
@@ -38,7 +38,7 @@ import org.apache.jena.update.* ;
 
 public class UpdateProgrammatic
 {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     public static void main(String []args)
     {
         Dataset dataset = DatasetFactory.createTxnMem() ;
diff --git a/jena-arq/src-examples/arq/examples/update/UpdateReadFromFile.java b/jena-arq/src-examples/arq/examples/update/UpdateReadFromFile.java
index 3eea6b5..03fc086 100644
--- a/jena-arq/src-examples/arq/examples/update/UpdateReadFromFile.java
+++ b/jena-arq/src-examples/arq/examples/update/UpdateReadFromFile.java
@@ -29,7 +29,7 @@ import org.apache.jena.update.* ;
 /** Simple example of SPARQL/Update : read a update script from a file and execute it */ 
 public class UpdateReadFromFile
 {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     public static void main(String []args)
     {
         // Create an empty GraphStore (has an empty default graph and no named graphs) 
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/pfunction/library/triple/TripleTermFind.java b/jena-arq/src/main/java/org/apache/jena/sparql/pfunction/library/triple/TripleTermFind.java
index c033ff1..30fab8b 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/pfunction/library/triple/TripleTermFind.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/pfunction/library/triple/TripleTermFind.java
@@ -34,8 +34,8 @@ import org.apache.jena.sparql.pfunction.*;
 
 /** Property function for FIND() - allows already bound.
  * <pre>
- *    << ?s ?p ?o >> apf:find ?t .
- * <pre>
+ *    &lt;&lt; ?s ?p ?o &gt;&gt; apf:find ?t .
+ * </pre>
  * This binds all the variables, with <tt>?t</tt> bound to a triple term for the match of <tt>?s ?p ?o</tt>. 
  */ 
 public class TripleTermFind extends PropertyFunctionEval {
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCmd.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCmd.java
new file mode 100644
index 0000000..6a011a9
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCmd.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.atlas.logging;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.jena.atlas.io.IO;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory;
+
+/** 
+ * Additional logging control, for Log4j2 as used by jena-cmds.
+ * <br/> 
+ * This class pulls in log4j2.
+ * <br/>
+ * This class is split out from {@link LogCtl} to decouple the class loading dependencies.
+ */
+public class LogCmd {
+    /**
+     * Reset logging (log4j2). log4j2.properties format.
+     */
+    public static void resetLogging(String configString) {
+        // Dispatch name to syntax.
+        try (InputStream inputStream = new ByteArrayInputStream(StrUtils.asUTF8bytes(configString))) {
+            resetLogging(inputStream, ".properties");
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
+    }
+
+    private static void resetLogging(InputStream inputStream, String syntaxHint) throws IOException {
+        ConfigurationSource source = new ConfigurationSource(inputStream);
+        ConfigurationFactory factory = ( syntaxHint.endsWith(".properties") )
+            ? new PropertiesConfigurationFactory()
+            : ConfigurationFactory.getInstance();
+        Configuration configuration = factory.getConfiguration(null, source);
+        Configurator.initialize(configuration);
+    }
+    
+//    public static void setCmdLogging() {
+//        LogCtl.setLog4j2();
+//        if ( ! LogCtl.isSetLog4j2property() )
+//            resetLogging(log4j2setupCmd);
+//    }
+
+    // basic setup.
+    // @formatter:off
+    /** A basic logging setup. */
+    public static String log4j2setup = StrUtils.strjoinNL
+        ( "## Command default log4j2 setup : log4j2 properties syntax."
+        , "status = error"
+        , "name = PropertiesConfig"
+        , "filters = threshold"
+        , ""
+        , "filter.threshold.type = ThresholdFilter"
+        , "filter.threshold.level = INFO"
+
+        , "appender.console.type = Console"
+        , "appender.console.name = OUT"
+        , "appender.console.target = SYSTEM_OUT"
+        , "appender.console.layout.type = PatternLayout"
+        , "appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-10c{1} :: %m%n"
+        , "#appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-10c{1} :: %m%n"
+
+        , "rootLogger.level                  = INFO"
+        , "rootLogger.appenderRef.stdout.ref = OUT"
+
+        , "logger.jena.name  = org.apache.jena"
+        , "logger.jena.level = INFO"
+
+        , "logger.arq-exec.name  = org.apache.jena.arq.exec"
+        , "logger.arq-exec.level = INFO"
+
+        , "logger.riot.name  = org.apache.jena.riot"
+        , "logger.riot.level = INFO"
+        );
+    // @formatter:on
+    
+    
+    // @formatter:off
+    /** A format for commands using stderr. */
+    public static String log4j2setupCmd = StrUtils.strjoinNL
+        ( "## Command default log4j2 setup : log4j2 properties syntax."
+        , "status = error"
+        , "name = PropertiesConfig"
+        , "filters = threshold"
+        , ""
+        , "filter.threshold.type = ThresholdFilter"
+        , "filter.threshold.level = INFO"
+
+        , "appender.console.type = Console"
+        , "appender.console.name = OUT"
+        , "appender.console.target = SYSTEM_ERR"
+        , "appender.console.layout.type = PatternLayout"
+        , "appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-10c{1} :: %m%n"
+        , "#appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-10c{1} ::: %m%n"
+
+        , "rootLogger.level                  = INFO"
+        , "rootLogger.appenderRef.stdout.ref = OUT"
+
+        , "logger.jena.name  = org.apache.jena"
+        , "logger.jena.level = INFO"
+
+        , "logger.arq-exec.name  = org.apache.jena.arq.exec"
+        , "logger.arq-exec.level = INFO"
+
+        , "logger.riot.name  = org.apache.jena.riot"
+        , "logger.riot.level = INFO"
+        );
+    // @formatter:on
+
+}
+
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
index e61e33a..460b7bf 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
@@ -18,23 +18,25 @@
 
 package org.apache.jena.atlas.logging;
 
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.apache.jena.atlas.AtlasException;
-import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.lib.StrUtils;
+import java.io.File;
+
 import org.slf4j.Logger;
 
-/** Setup and control of logging - needs access to log4j2 binaries */ 
+/**
+ * Setup and control of logging - needs access to log4j2 binaries.
+ * Sources of configuration:
+ * <ul>
+ * <li>Standard setup (e.g. for log4j2, property {@code log4j.configurationFile}
+ * <li>jena-cmds: the shell scripts set logging to "apache-jena/log4j2.properties." (uses stderr)
+ * <li>Default logging for log4j2: java resource src/main/resources/log4j-jena.properties (uses stdout)
+ * </ul>
+ */
 public class LogCtl {
-    
-    private static final boolean hasLog4j1 = hasClass("org.slf4j.impl.Log4jLoggerFactory");
     private static final boolean hasLog4j2 = hasClass("org.apache.logging.slf4j.Log4jLoggerFactory");
-    // JUL always present.
-    
+    private static final boolean hasLog4j1 = hasClass("org.slf4j.impl.Log4jLoggerFactory");
+    private static final boolean hasJUL    = hasClass("org.slf4j.impl.JDK14LoggerFactory");
+    // JUL always present but needs slf4j adpater.
+
     private static boolean hasClass(String className) {
         try {
             Class.forName(className);
@@ -51,25 +53,25 @@ public class LogCtl {
     static public void setLevel(Class<? > logger, String level) {
         setLevel(logger.getName(), level);
     }
-    
+
     static public void setLevel(Logger logger, String level) {
         setLevel(logger.getName(), level);
     }
-    
+
     static public void setLevel(String logger, String level) {
-        //setLevelLog4j1(logger,level);
-        setLevelLog4j2(logger,level);
-        setLevelJUL(logger,level);
+        // setLevelLog4j1(logger,level);
+        setLevelLog4j2(logger, level);
+        setLevelJUL(logger, level);
     }
 
     static public String getLevel(Logger logger) {
         return getLevel(logger.getName());
     }
-    
+
     static public String getLevel(Class<? > logger) {
         return getLevel(logger.getName());
     }
-    
+
     static public String getLevel(String logger) {
         String s2 = getLevelLog4j2(logger);
         if ( s2 != null )
@@ -82,33 +84,32 @@ public class LogCtl {
     }
 
     static private String getLevelJUL(String logger) {
-        java.util.logging.Level level = 
-            java.util.logging.Logger.getLogger(logger).getLevel();
+        java.util.logging.Level level = java.util.logging.Logger.getLogger(logger).getLevel();
         if ( level == null )
             return null;
         if ( level == java.util.logging.Level.SEVERE )
             return "ERROR";
         return level.getName();
     }
-    
+
     static private String getLevelLog4j2(String logger) {
-        if ( ! hasLog4j2 )
+        if ( !hasLog4j2 )
             return null;
         org.apache.logging.log4j.Level level = org.apache.logging.log4j.LogManager.getLogger(logger).getLevel();
-        if ( level != null )   
-            return level.toString();            
+        if ( level != null )
+            return level.toString();
         return null;
     }
-    
+
     private static void setLevelJUL(String logger, String levelName) {
         java.util.logging.Level level = java.util.logging.Level.ALL;
-        if ( levelName == null ) 
+        if ( levelName == null )
             level = null;
         else if ( levelName.equalsIgnoreCase("info") )
             level = java.util.logging.Level.INFO;
         else if ( levelName.equalsIgnoreCase("debug") )
             level = java.util.logging.Level.FINE;
-        else if ( levelName.equalsIgnoreCase("warn") || levelName.equalsIgnoreCase("warning") ) 
+        else if ( levelName.equalsIgnoreCase("warn") || levelName.equalsIgnoreCase("warning") )
             level = java.util.logging.Level.WARNING;
         else if ( levelName.equalsIgnoreCase("error") || levelName.equalsIgnoreCase("severe") )
             level = java.util.logging.Level.SEVERE;
@@ -118,10 +119,10 @@ public class LogCtl {
     }
 
     private static void setLevelLog4j2(String logger, String levelName) {
-        if ( ! hasLog4j2 )
+        if ( !hasLog4j2 )
             return;
         org.apache.logging.log4j.Level level = org.apache.logging.log4j.Level.ALL;
-        if ( levelName == null ) 
+        if ( levelName == null )
             level = null;
         else if ( levelName.equalsIgnoreCase("info") )
             level = org.apache.logging.log4j.Level.INFO;
@@ -136,7 +137,8 @@ public class LogCtl {
         else if ( levelName.equalsIgnoreCase("OFF") )
             level = org.apache.logging.log4j.Level.OFF;
         try {
-            // "try" : If log4j2 core is not on the path (everything else is log4j-api).
+            // "try" : If log4j2 core is not on the path (everything else is
+            // log4j-api).
             if ( !logger.equals("") )
                 org.apache.logging.log4j.core.config.Configurator.setLevel(logger, level);
             else
@@ -147,8 +149,8 @@ public class LogCtl {
     }
 
     /**
-     * Turn on a logger (all levels). Works for Log4j and Java logging as the
-     * logging provider to Apache common logging or slf4j.
+     * Turn on a logger (all levels). Works for Log4j and Java logging as the logging
+     * provider to Apache common logging or slf4j.
      */
     static public void enable(Logger logger) {
         enable(logger.getName());
@@ -159,270 +161,188 @@ public class LogCtl {
     }
 
     /**
-     * Turn on a logger (all levels). Works for Log4j and Java logging as the
-     * logging provider to Apache common logging or slf4j.
+     * Turn on a logger (all levels). Works for Log4j and Java logging as the logging
+     * provider to Apache common logging or slf4j.
      */
     static public void enable(Class<? > logger) {
         setLevel(logger.getName(), "ALL");
     }
 
     /**
-     * Turn on a logger (all levels). Works for Log4j and Java logging as the
-     * logging provider to Apache common logging or slf4j.
+     * Turn on a logger (all levels). Works for Log4j and Java logging as the logging
+     * provider to Apache common logging or slf4j.
      */
     static public void disable(Logger logger) {
         setLevel(logger.getName(), "OFF");
     }
 
     /**
-     * Turn on a logger (all levels). Works for Log4j and Java logging as the
-     * logging provider to Apache common logging or slf4j.
+     * Turn on a logger (all levels). Works for Log4j and Java logging as the logging
+     * provider to Apache common logging or slf4j.
      */
     static public void disable(String logger) {
         setLevel(logger, "OFF");
     }
 
     /**
-     * Turn on a logger (all levels). Works for Log4j and Java logging as the
-     * logging provider to Apache common logging or slf4j.
+     * Turn on a logger (all levels). Works for Log4j and Java logging as the logging
+     * provider to Apache common logging or slf4j.
      */
     static public void disable(Class<? > logger) {
         setLevel(logger.getName(), "OFF");
     }
 
     /**
-     * Set to info level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to info level. Works for Log4j and Java logging as the logging provider to
+     * Apache common logging or slf4j.
      */
     static public void setInfo(String logger) {
         setLevel(logger, "info");
     }
 
     /**
-     * Set to info level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to info level. Works for Log4j and Java logging as the logging provider to
+     * Apache common logging or slf4j.
      */
     static public void setInfo(Class<? > logger) {
         setLevel(logger.getName(), "info");
     }
 
     /**
-     * Set to warning level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to warning level. Works for Log4j and Java logging as the logging provider
+     * to Apache common logging or slf4j.
      */
     static public void setWarn(String logger) {
         setLevel(logger, "warn");
     }
 
     /**
-     * Set to warning level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to warning level. Works for Log4j and Java logging as the logging provider
+     * to Apache common logging or slf4j.
      */
     static public void setWarn(Class<? > logger) {
         setLevel(logger.getName(), "warn");
     }
 
     /**
-     * Set to error level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to error level. Works for Log4j and Java logging as the logging provider
+     * to Apache common logging or slf4j.
      */
     static public void setError(String logger) {
         setLevel(logger, "error");
     }
 
     /**
-     * Set to error level. Works for Log4j and Java logging as the logging
-     * provider to Apache common logging or slf4j.
+     * Set to error level. Works for Log4j and Java logging as the logging provider
+     * to Apache common logging or slf4j.
      */
     static public void setError(Class<? > logger) {
         setLevel(logger.getName(), "error");
     }
 
-    private static String log4j2setup = StrUtils.strjoinNL
-        ( "## Command default log4j2 setup : log4j2 properties syntax."
-        , "status = error"
-        , "name = PropertiesConfig"
-        , "filters = threshold"
-        , ""
-        , "filter.threshold.type = ThresholdFilter"
-        , "filter.threshold.level = INFO"
-
-        , "appender.console.type = Console"
-        , "appender.console.name = OUT"
-        , "appender.console.target = SYSTEM_ERR"
-        , "appender.console.layout.type = PatternLayout"
-        , "appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-10c{1} :: %m%n"
-        , "#appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-10c{1} :: %m%n"
-
-        , "rootLogger.level                  = INFO"
-        , "rootLogger.appenderRef.stdout.ref = OUT"
-
-        , "logger.jena.name  = org.apache.jena"
-        , "logger.jena.level = INFO"
-
-        , "logger.arq-exec.name  = org.apache.jena.arq.exec"
-        , "logger.arq-exec.level = INFO"
-
-        , "logger.riot.name  = org.apache.jena.riot"
-        , "logger.riot.level = INFO"
-        );
+    // ---- Setup
 
     /**
-     * Set logging
-     * <ol>
-     * <li>Check for -Dlog4j.configurationFile.</li>
-     * <li>Looks for log4j.properties file in current directory.</li>
-     * </ol>
-     * Return true if we think Log4J is not initialized.
+     * Set logging.
+     * <p>
+     * Normally, the logging provider mechanism should be used.
+     * This call will insert some kind of logging set for JUL and Log4j2
+     * when no configuration is setup; output is to stdout.
+     * <p>
+     * Ideally, initialize the logging provider using the mechanism specific to that provider.
+     * For example, see the <a href="https://logging.apache.org/log4j/2.x/manual/configuration.html">log4j2 configuration documentation</a>.  
+     * <p>
+     * To set application logging, choose one of:
+     * <ul>
+     * <li>For JUL logging, have a dependency on artifact {@code org.slf4j:slf4j-jdk14}.
+     * <li>For log4j2 logging, have a dependency on artifact {@code org.apache.logging.log4j:log4j-slf4j-impl}.
+     * </ul>
      */
-    
-    public static void setLog4j() {
-        System.err.println("Log4j1 supported removed. Please use setLog4j2.");
-    }
-    
-    /** Set log4j properties (XML or properties file) */
-    public static void setLog4j(String filename) {
-        System.err.println("Log4j1 supported removed. Please use setLog4j2.");
-    }
-    
-    private static String[] log4j2files = {"log4j2.properties","log4j2.xml"};
-    
-    public static void setLog4j2() {
-        if ( System.getProperty("log4j2.configurationFile") == null ) {
-            for ( String fn : log4j2files ) {
-                File f = new File(fn);
-                if ( f.exists() )
-                    System.setProperty("log4j.configurationFile", "file:" + fn);
-            }
+    public static void setLogging() {
+        // Assumes log4j2 or JUL (and slf4j adapters) on the classpath.
+        if ( hasLog4j2 ) {
+            setLog4j2();
+            return;
+        }
+        if ( hasJUL ) {
+            setJavaLogging();
+            return;
         }
     }
-    
-    public static void setLog4j2(String filename) {
-        if ( ! filename.startsWith("file:") )
-            filename = "file:"+filename;
-        System.setProperty("log4j.configurationFile", "file:" + filename);
-    }
-    
+
     /**
-     * Set logging, suitable for a command line application.
-     * If "log4j.configurationFile" not set, then use the built-in default, 
-     * else just leave to log4j2 startup.
+     * @deprecated Use {@link #setLogging}.
      */
+    @Deprecated
     public static void setCmdLogging() {
-        setCmdLogging(log4j2setup);
+        setLogging();
     }
 
     /**
-     * Set logging, suitable for a command line application.
-     * If "log4j.configurationFile" not set, then use the provided default 
-     * (log4j2 properties syntax) else just leave to log4j2 startup.
+     * @deprecated Use {@link #setLog4j2}
      */
-    public static void setCmdLogging(String defaultConfig) {
-        if (System.getProperty("log4j.configurationFile") == null ) {
-            resetLogging(defaultConfig);
-            System.setProperty("log4j.configurationFile", "set");
-        }
+    @Deprecated
+    public static void setLog4j() {
+        System.err.println("Log4j1 supported removed. Please use setLog4j2.");
     }
 
     /**
-     * Reset logging (log4j2). log4j2.properties format.
+     * @deprecated Use logging provider setup. For log4j2, use system property "log4j.configurationFile"
      */
-    public static void resetLogging(String configString) {
-        if ( hasLog4j1 ) {
-            System.err.println("WARNING: slf4j-log4j1 adapter detected. Use log4j2.");
-        }
-        if ( ! hasLog4j2 )
-            return;
-
-        // Dispatch name to syntax.
-        try ( InputStream inputStream = new ByteArrayInputStream(StrUtils.asUTF8bytes(configString)) ) {
-            resetLogging(inputStream, ".properties");
-        } catch (IOException ex) { IO.exception(ex); }
+    @Deprecated
+    public static void setLog4j(String filename) {
+        System.err.println("Log4j1 supported removed. Please use setLog4j2.");
     }
 
-    private static void resetLogging(InputStream inputStream, String syntaxHint) throws IOException {
-        org.apache.logging.log4j.core.config.ConfigurationSource source = new org.apache.logging.log4j.core.config.ConfigurationSource(inputStream);
-        org.apache.logging.log4j.core.config.ConfigurationFactory factory;
-        if ( syntaxHint.endsWith(".properties" ) )
-            factory = new org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory();
-        else
-            factory = org.apache.logging.log4j.core.config.ConfigurationFactory.getInstance();
+    // ---- log4j2.
 
-        org.apache.logging.log4j.core.config.Configuration configuration = factory.getConfiguration(null, source);
-        org.apache.logging.log4j.core.config.Configurator.initialize(configuration);
-    }
+    /** The log4j2 configuration file - must be a file or URL, not a classpath java resource */ 
+    public static final String log4j2ConfigProperty = "log4j.configurationFile";
 
-    // ---- java.util.logging - because that's always present.
-    // Need:  org.slf4j:slf4j-jdk14
-    private static String defaultProperties = StrUtils.strjoinNL
-        ("handlers=org.apache.jena.atlas.logging.java.ConsoleHandlerStream"
-        // These are the defaults.
-        //,"org.apache.jena.atlas.logging.java.ConsoleHandlerStream.level=INFO"
-        //,"org.apache.jena.atlas.logging.java.ConsoleHandlerStream.formatter=org.apache.jena.atlas.logging.java.TextFormatter"
-        //,"org.apache.jena.atlas.logging.java.TextFormatter.format=%5$tT %3$-5s %2$-20s :: %6$s"
-        );
-    // File or java resource name default.
-    private static String JUL_LOGGING = "logging.properties";
-    
-    // JUL will close existing logger if logging is reset.
-    // This includes StreamHandler logging to stdout.  Stdout is closed.
-    // This property controls setJavaLogging() acting multiple times.
-    private static String JUL_PROPERTY = "java.util.logging.configuration";
+    private static final String[] log4j2files = {"log4j2.properties", "log4j2.xml"};
 
-    /** Setup java.util.logging if it has not been set before; otherwise do nothing. */
-    public static void setJavaLogging() {
-        if ( System.getProperty(JUL_PROPERTY) != null )
-            return;
-        resetJavaLogging();
-    }
-    
-    /** Reset java.util.logging - this overrides the previous configuration, if any. */  
-    public static void resetJavaLogging() {
-        Path p = Paths.get(JUL_LOGGING);
-        if ( Files.exists(p) ) {
-            setJavaLogging(JUL_LOGGING);
-            return;
+    /**
+     * Setup log4j2, including looking for a file "log4j2.properties" or "log4j2.xml"
+     * in the current working directory.
+     * @see #setLogging()
+     */
+    public static void setLog4j2() {
+        if ( ! isSetLog4j2property() ) {
+            setLog4j2property();
+            if ( isSetLog4j2property() ) 
+                return;
+            // Nothing found - built-in default.
+            LogCmd.resetLogging(LogCmd.log4j2setup);
         }
-        if ( setJavaLoggingClasspath(JUL_LOGGING) )
-            return;
-        setJavaLoggingDft();
     }
 
-    private static void readJavaLoggingConfiguration(InputStream details) throws Exception {
-        System.setProperty(JUL_PROPERTY, "set");
-        java.util.logging.LogManager.getLogManager().readConfiguration(details);
+    /*package*/ static boolean isSetLog4j2property() {
+        return System.getProperty(log4j2ConfigProperty) != null ;
     }
     
-    private static boolean setJavaLoggingClasspath(String resourceName) {
-        // Not "LogCtl.class.getResourceAsStream(resourceName)" which monkeys around with the resourceName.
-        InputStream in = LogCtl.class.getClassLoader().getResourceAsStream(resourceName);
-        if ( in != null ) {
-            try {
-                readJavaLoggingConfiguration(in);
-                return true; 
-            } catch (Exception ex) {
-                throw new AtlasException(ex);
+    /** Set log4j, looking for files */ 
+    /*package*/ static void setLog4j2property() {
+        if ( isSetLog4j2property() )
+            return;
+        for ( String fn : log4j2files ) {
+            File f = new File(fn);
+            if ( f.exists() ) {
+                System.setProperty(log4j2ConfigProperty, "file:" + fn);
+                return;
             }
         }
-        return false;
-    }
-
-    public static void setJavaLogging(String file) {
-        try {
-            InputStream details = new FileInputStream(file);
-            details = new BufferedInputStream(details);
-            readJavaLoggingConfiguration(details);
-        } catch (Exception ex) {
-            throw new AtlasException(ex);
-        }
     }
-
-    public static void setJavaLoggingDft() {
-        try {
-            InputStream details = new ByteArrayInputStream(defaultProperties.getBytes("UTF-8"));
-            readJavaLoggingConfiguration(details);
-        } catch (Exception ex) {
-            throw new AtlasException(ex);
-        }
+    
+    // ---- java.util.logging - because that's always present.
+    // Need: org.slf4j:slf4j-jdk14
+    
+    private static String JUL_PROPERTY      = "java.util.logging.configuration";
+    /**
+     * Setup java.util.logging if it has not been set before; otherwise do nothing.
+     */
+    public static void setJavaLogging() {
+        if ( System.getProperty(JUL_PROPERTY) != null )
+            return;
+        LogJUL.resetJavaLogging();
     }
 }
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/LogJUL.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogJUL.java
new file mode 100644
index 0000000..f3448f5
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogJUL.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.atlas.logging;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.jena.atlas.AtlasException;
+import org.apache.jena.atlas.lib.StrUtils;
+
+/** java.util.logging specific code. */
+public class LogJUL {
+    // File or java resource name default.
+    public static String JUL_LOGGING       = "logging.properties";
+
+    // JUL will close existing logger if logging is reset.
+    // This includes StreamHandler logging to stdout. Stdout is closed.
+    // This property controls setJavaLogging() acting multiple times.
+    private static String JUL_PROPERTY      = "java.util.logging.configuration";
+
+    // @formatter:on
+    static String defaultProperties = StrUtils.strjoinNL
+        ("handlers=org.apache.jena.atlas.logging.java.ConsoleHandlerStream"
+        // These are the defaults in o.a.jena.logging.java
+        // ,"org.apache.jena.atlas.logging.java.ConsoleHandlerStream.level=INFO"
+        // ,"org.apache.jena.atlas.logging.java.ConsoleHandlerStream.formatter=org.apache.jena.atlas.logging.java.TextFormatter"
+        //,"org.apache.jena.atlas.logging.java.TextFormatter.format=%5$tT %3$-5s %2$-20s :: %6$s"
+        );
+    // @formatter:off
+    
+    /**
+     * Reset java.util.logging - this overrides the previous configuration, if any.
+     */
+    static void resetJavaLogging() {
+        Path p = Paths.get(JUL_LOGGING);
+        if ( Files.exists(p) ) {
+            setJavaLogging(JUL_LOGGING);
+            return;
+        }
+        if ( setJavaLoggingClasspath(JUL_LOGGING) )
+            return;
+        setJavaLoggingDft();
+    }
+
+    static void readJavaLoggingConfiguration(InputStream details) throws Exception {
+        System.setProperty(JUL_PROPERTY, "set");
+        java.util.logging.LogManager.getLogManager().readConfiguration(details);
+    }
+
+    private static boolean setJavaLoggingClasspath(String resourceName) {
+        // Not "LogCtl.class.getResourceAsStream(resourceName)" which monkeys around
+        // with the resourceName.
+        InputStream in = LogCtl.class.getClassLoader().getResourceAsStream(resourceName);
+        if ( in != null ) {
+            try {
+                readJavaLoggingConfiguration(in);
+                return true;
+            } catch (Exception ex) {
+                throw new AtlasException(ex);
+            }
+        }
+        return false;
+    }
+
+    public static void setJavaLogging(String file) {
+        try {
+            InputStream details = new FileInputStream(file);
+            details = new BufferedInputStream(details);
+            readJavaLoggingConfiguration(details);
+        } catch (Exception ex) {
+            throw new AtlasException(ex);
+        }
+    }
+
+    public static void setJavaLoggingDft() {
+        try {
+            InputStream details = new ByteArrayInputStream(defaultProperties.getBytes("UTF-8"));
+            readJavaLoggingConfiguration(details);
+        } catch (Exception ex) {
+            throw new AtlasException(ex);
+        }
+    }
+
+}
+
diff --git a/jena-cmds/src/main/java/arq/qexpr.java b/jena-cmds/src/main/java/arq/qexpr.java
index 8a3ef41..171a468 100644
--- a/jena-cmds/src/main/java/arq/qexpr.java
+++ b/jena-cmds/src/main/java/arq/qexpr.java
@@ -49,7 +49,7 @@ import org.apache.jena.sys.JenaSystem ;
 public class qexpr
 {
     static {
-        LogCtl.setCmdLogging() ;
+        LogCtl.setLogging() ;
         JenaSystem.init() ;
     }
 
diff --git a/jena-cmds/src/main/java/arq/rdfdiff.java b/jena-cmds/src/main/java/arq/rdfdiff.java
index 37e6e91..c9cd303 100644
--- a/jena-cmds/src/main/java/arq/rdfdiff.java
+++ b/jena-cmds/src/main/java/arq/rdfdiff.java
@@ -18,7 +18,7 @@
 
 package arq;
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.net.URL;
 import java.util.ArrayList;
@@ -59,7 +59,7 @@ import org.apache.jena.sparql.util.Closure;
 public class rdfdiff extends java.lang.Object {
 
     static {
-        setCmdLogging();
+        setLogging();
     }
 
     /**
diff --git a/jena-cmds/src/main/java/jena/RuleMap.java b/jena-cmds/src/main/java/jena/RuleMap.java
index 111f44b..9129e8e 100644
--- a/jena-cmds/src/main/java/jena/RuleMap.java
+++ b/jena-cmds/src/main/java/jena/RuleMap.java
@@ -19,7 +19,7 @@
 package jena;
 
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.util.*;
 import java.io.*;
@@ -53,7 +53,7 @@ import org.apache.jena.util.FileUtils ;
  * </p>
  */
 public class RuleMap {
-    static { setCmdLogging() ; }
+    static { setLogging() ; }
     
     /**
      * Load a set of rule definitions including processing of
diff --git a/jena-cmds/src/main/java/jena/cmd/CmdMain.java b/jena-cmds/src/main/java/jena/cmd/CmdMain.java
index 4148509..331a869 100644
--- a/jena-cmds/src/main/java/jena/cmd/CmdMain.java
+++ b/jena-cmds/src/main/java/jena/cmd/CmdMain.java
@@ -33,7 +33,7 @@ public abstract class CmdMain extends CmdLineArgs
 {
     // Do this very early so it happens before anything else
     // gets a chance to create a logger.
-    static { LogCtl.setCmdLogging() ; }
+    static { LogCtl.setLogging() ; }
     
     public CmdMain(String[] args)
     {
diff --git a/jena-cmds/src/main/java/jena/rdfcat.java b/jena-cmds/src/main/java/jena/rdfcat.java
index cb3ad6d..356e255 100644
--- a/jena-cmds/src/main/java/jena/rdfcat.java
+++ b/jena-cmds/src/main/java/jena/rdfcat.java
@@ -24,7 +24,7 @@ package jena;
 // Imports
 ///////////////
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.io.OutputStream ;
 import java.util.* ;
@@ -121,7 +121,10 @@ import org.apache.jena.vocabulary.RDFS ;
 @Deprecated
 public class rdfcat
 {
-    static { setCmdLogging("jena-log4j.properties") ; }
+    static { 
+        setLogging(); 
+        JenaSystem.init();
+    }
     
     /** The merged model containing all of the inputs */
     protected Model m_model = ModelFactory.createDefaultModel();
diff --git a/jena-cmds/src/main/java/jena/rdfcompare.java b/jena-cmds/src/main/java/jena/rdfcompare.java
index 5f23157..646ef1f 100644
--- a/jena-cmds/src/main/java/jena/rdfcompare.java
+++ b/jena-cmds/src/main/java/jena/rdfcompare.java
@@ -18,7 +18,7 @@
 
 package jena;
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import org.apache.jena.rdf.model.Model ;
 import org.apache.jena.rdf.model.ModelFactory ;
@@ -50,9 +50,9 @@ import org.apache.jena.sys.JenaSystem ;
  */
 public class rdfcompare extends java.lang.Object {
 
-    static {
+    static { 
+        setLogging(); 
         JenaSystem.init();
-        setCmdLogging();
     }
 
     /**
diff --git a/jena-cmds/src/main/java/jena/rdfcopy.java b/jena-cmds/src/main/java/jena/rdfcopy.java
index a998c37..64adc9d 100644
--- a/jena-cmds/src/main/java/jena/rdfcopy.java
+++ b/jena-cmds/src/main/java/jena/rdfcopy.java
@@ -18,7 +18,7 @@
 
 package jena;
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.net.*;
 import java.io.*;
@@ -52,7 +52,7 @@ import org.apache.jena.shared.JenaException ;
  */
 public class rdfcopy extends java.lang.Object {
 
-    static { setCmdLogging(); }
+    static { setLogging(); }
 
 	/**
 	* @param args the command line arguments
diff --git a/jena-cmds/src/main/java/jena/rdfparse.java b/jena-cmds/src/main/java/jena/rdfparse.java
index 0ba1eb6..2785d82 100644
--- a/jena-cmds/src/main/java/jena/rdfparse.java
+++ b/jena-cmds/src/main/java/jena/rdfparse.java
@@ -18,7 +18,7 @@
 
 package jena;
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.lang.reflect.Constructor ;
 
@@ -77,7 +77,7 @@ import org.apache.jena.shared.Command ;
 
 public class rdfparse {
 
-    static { setCmdLogging(); }
+    static { setLogging(); }
 
     /** Either start an RDF/XML to NTriple converter, or run test suite.
 	 * @param args The command-line arguments.
diff --git a/jena-cmds/src/main/java/jena/schemagen.java b/jena-cmds/src/main/java/jena/schemagen.java
index 05715b7..ee4c3b1 100644
--- a/jena-cmds/src/main/java/jena/schemagen.java
+++ b/jena-cmds/src/main/java/jena/schemagen.java
@@ -21,7 +21,7 @@
 package jena;
 
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import java.io.ByteArrayOutputStream ;
 import java.io.File ;
@@ -59,7 +59,7 @@ import org.apache.jena.vocabulary.XSD ;
  */
 public class schemagen {
     
-    static { setCmdLogging(); }
+    static { setLogging(); }
 
     // Constants
     //////////////////////////////////
diff --git a/jena-cmds/src/main/java/jena/version.java b/jena-cmds/src/main/java/jena/version.java
index 01f6dd3..cf9a066 100644
--- a/jena-cmds/src/main/java/jena/version.java
+++ b/jena-cmds/src/main/java/jena/version.java
@@ -18,7 +18,7 @@
 
 package jena;
 
-import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging;
+import static org.apache.jena.atlas.logging.LogCtl.setLogging;
 
 import org.apache.jena.Jena ;
 
@@ -28,7 +28,7 @@ import org.apache.jena.Jena ;
  */
 public class version implements Jena {
 
-    static { setCmdLogging(); }
+    static { setLogging(); }
 
     /**
      * Print out jena version information and exits.
diff --git a/jena-cmds/src/main/java/riotcmd/dumpthrift.java b/jena-cmds/src/main/java/riotcmd/dumpthrift.java
index d18c3f5..63a260b 100644
--- a/jena-cmds/src/main/java/riotcmd/dumpthrift.java
+++ b/jena-cmds/src/main/java/riotcmd/dumpthrift.java
@@ -28,7 +28,7 @@ import org.apache.jena.sys.JenaSystem ;
 
 /** Dump an rdf-thrift file to show structure */ 
 public class dumpthrift {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
     static { JenaSystem.init() ; }
     
     public static void main(String... args) {
diff --git a/jena-cmds/src/main/java/shacl/shacl.java b/jena-cmds/src/main/java/shacl/shacl.java
index 570fc80..37c4c76 100644
--- a/jena-cmds/src/main/java/shacl/shacl.java
+++ b/jena-cmds/src/main/java/shacl/shacl.java
@@ -28,7 +28,7 @@ import org.apache.jena.sys.JenaSystem;
 
 public class shacl {
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-cmds/src/main/java/shacl/shacl_parse.java b/jena-cmds/src/main/java/shacl/shacl_parse.java
index 14718c1..75a44fb 100644
--- a/jena-cmds/src/main/java/shacl/shacl_parse.java
+++ b/jena-cmds/src/main/java/shacl/shacl_parse.java
@@ -32,7 +32,7 @@ import org.apache.jena.sys.JenaSystem;
 public class shacl_parse extends CmdGeneral {
 
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
     private String shapesfile = null;
diff --git a/jena-cmds/src/main/java/shacl/shacl_validate.java b/jena-cmds/src/main/java/shacl/shacl_validate.java
index 901cb4f..5fec37a 100644
--- a/jena-cmds/src/main/java/shacl/shacl_validate.java
+++ b/jena-cmds/src/main/java/shacl/shacl_validate.java
@@ -40,7 +40,7 @@ import org.apache.jena.sys.JenaSystem;
 public class shacl_validate extends CmdGeneral {
 
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexBuild.java b/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexBuild.java
index 596e446..670c0fa 100644
--- a/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexBuild.java
+++ b/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexBuild.java
@@ -24,7 +24,7 @@ import org.apache.jena.tdb.store.bulkloader2.ProcIndexBuild ;
 
 public class CmdIndexBuild {
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
     
diff --git a/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexCopy.java b/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexCopy.java
index 345386b..2373676 100644
--- a/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexCopy.java
+++ b/jena-cmds/src/main/java/tdb/bulkloader2/CmdIndexCopy.java
@@ -25,7 +25,7 @@ import org.apache.jena.tdb.store.bulkloader2.ProcIndexCopy ;
 public class CmdIndexCopy 
 {
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-cmds/src/main/java/tdb/bulkloader2/CmdNodeTableBuilder.java b/jena-cmds/src/main/java/tdb/bulkloader2/CmdNodeTableBuilder.java
index 9e90271..432273d 100644
--- a/jena-cmds/src/main/java/tdb/bulkloader2/CmdNodeTableBuilder.java
+++ b/jena-cmds/src/main/java/tdb/bulkloader2/CmdNodeTableBuilder.java
@@ -39,7 +39,7 @@ import tdb.cmdline.CmdTDB ;
 public class CmdNodeTableBuilder extends CmdGeneral
 {
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-cmds/src/main/java/tdb/bulkloader2/CmdRewriteIndex.java b/jena-cmds/src/main/java/tdb/bulkloader2/CmdRewriteIndex.java
index 56f1c45..af094d0 100644
--- a/jena-cmds/src/main/java/tdb/bulkloader2/CmdRewriteIndex.java
+++ b/jena-cmds/src/main/java/tdb/bulkloader2/CmdRewriteIndex.java
@@ -30,7 +30,7 @@ import org.apache.jena.tdb.sys.Names ;
 public class CmdRewriteIndex
 {
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-cmds/src/main/java/tdb/tools/dumpbpt.java b/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
index eb10535..ddf228c 100644
--- a/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
+++ b/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
@@ -48,7 +48,7 @@ public class dumpbpt extends CmdARQ {
     ModLocation modLocation = new ModLocation() ;
 
     static public void main(String... argv) {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         new dumpbpt(argv).mainRun() ;
     }
 
diff --git a/jena-cmds/src/main/java/tdb/tools/dumpjournal.java b/jena-cmds/src/main/java/tdb/tools/dumpjournal.java
index 0865bb4..9699f2a 100644
--- a/jena-cmds/src/main/java/tdb/tools/dumpjournal.java
+++ b/jena-cmds/src/main/java/tdb/tools/dumpjournal.java
@@ -33,7 +33,7 @@ public class dumpjournal extends CmdARQ {
     ModLocation modLocation = new ModLocation() ;
 
     static public void main(String... argv) {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         new dumpjournal(argv).mainRun() ;
     }
 
diff --git a/jena-cmds/src/main/java/tdb/tools/dumpnodes.java b/jena-cmds/src/main/java/tdb/tools/dumpnodes.java
index 17423d0..1e8bf0b 100644
--- a/jena-cmds/src/main/java/tdb/tools/dumpnodes.java
+++ b/jena-cmds/src/main/java/tdb/tools/dumpnodes.java
@@ -47,7 +47,7 @@ public class dumpnodes extends CmdARQ {
     ModLocation modLocation = new ModLocation() ;
 
     static public void main(String... argv) {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         new dumpnodes(argv).mainRun() ;
     }
 
diff --git a/jena-cmds/src/main/java/tdb2/cmdline/CmdTDB.java b/jena-cmds/src/main/java/tdb2/cmdline/CmdTDB.java
index 523f153..5806425 100644
--- a/jena-cmds/src/main/java/tdb2/cmdline/CmdTDB.java
+++ b/jena-cmds/src/main/java/tdb2/cmdline/CmdTDB.java
@@ -53,7 +53,7 @@ public abstract class CmdTDB extends CmdARQ
             return ;
         // attempt once.
         initialized = true ;
-        LogCtl.setCmdLogging() ;
+        LogCtl.setLogging() ;
     }
 
     @Override
diff --git a/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java b/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
index e433b3b..45d2a07 100644
--- a/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
+++ b/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
@@ -32,5 +32,5 @@ import org.junit.runners.Suite.SuiteClasses ;
 
 public class TS_Cmd
 {
-    static { LogCtl.setCmdLogging();}
+    static { LogCtl.setLogging();}
 }
diff --git a/jena-cmds/src/test/java/shacl/shacl_test.java b/jena-cmds/src/test/java/shacl/shacl_test.java
index 35585f7..2223950 100644
--- a/jena-cmds/src/test/java/shacl/shacl_test.java
+++ b/jena-cmds/src/test/java/shacl/shacl_test.java
@@ -27,7 +27,7 @@ import org.apache.jena.sys.JenaSystem;
 public class shacl_test extends CmdGeneral {
 
     static {
-        LogCtl.setCmdLogging();
+        LogCtl.setLogging();
         JenaSystem.init();
     }
 
diff --git a/jena-db/jena-dboe-base/src/test/java/org/apache/jena/dboe/base/block/TestBlockMgrMapped.java b/jena-db/jena-dboe-base/src/test/java/org/apache/jena/dboe/base/block/TestBlockMgrMapped.java
index 2163726..27a72cb 100644
--- a/jena-db/jena-dboe-base/src/test/java/org/apache/jena/dboe/base/block/TestBlockMgrMapped.java
+++ b/jena-db/jena-dboe-base/src/test/java/org/apache/jena/dboe/base/block/TestBlockMgrMapped.java
@@ -19,7 +19,6 @@
 package org.apache.jena.dboe.base.block;
 
 import org.apache.jena.atlas.lib.FileOps;
-import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.dboe.ConfigTestDBOE;
 import org.apache.jena.dboe.base.file.BlockAccess;
 import org.apache.jena.dboe.base.file.BlockAccessMapped;
@@ -29,10 +28,6 @@ import org.junit.BeforeClass;
 
 public class TestBlockMgrMapped extends AbstractTestBlockMgr
 {
-    static boolean logging = false;
-
-    static { if ( logging ) LogCtl.setLog4j(); }
-
     static final String filename = ConfigTestDBOE.getTestingDir()+"/block-mgr";
 
     // Windows is iffy about deleting memory mapped files.
diff --git a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/TS_JenaCommonsRDF.java b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/TS_JenaCommonsRDF.java
index b4f4dfd..3529745 100644
--- a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/TS_JenaCommonsRDF.java
+++ b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/TS_JenaCommonsRDF.java
@@ -18,8 +18,6 @@
 
 package org.apache.jena.commonsrdf;
 
-import org.apache.jena.atlas.logging.LogCtl;
-import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 
@@ -35,10 +33,5 @@ import org.junit.runners.Suite;
     , TestServiceLoaderCommonsRDF.class
 })
 
-public class TS_JenaCommonsRDF {
-    @BeforeClass public static void beforeClass() {
-        LogCtl.setLog4j();
-        //LogCtl.setWarn("org.apache.jena");
-    }
-}
+public class TS_JenaCommonsRDF {}
 
diff --git a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_JenaGraphToCommonsRDFGraph.java b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_JenaGraphToCommonsRDFGraph.java
index 7a681b2..516746c 100644
--- a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_JenaGraphToCommonsRDFGraph.java
+++ b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_JenaGraphToCommonsRDFGraph.java
@@ -29,7 +29,7 @@ import org.apache.jena.sparql.graph.GraphFactory;
 
 /** Adapt a Jena Graph after parsing data into it */
 public class Ex_JenaGraphToCommonsRDFGraph {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
 
     public static void main(String ...a) {
         org.apache.jena.graph.Graph jGraph = GraphFactory.createGraphMem();
diff --git a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_ParseIntoCommonsRDFGraph.java b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_ParseIntoCommonsRDFGraph.java
index 04714b4..f214b8f 100644
--- a/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_ParseIntoCommonsRDFGraph.java
+++ b/jena-extras/jena-commonsrdf/src/test/java/org/apache/jena/commonsrdf/examples/Ex_ParseIntoCommonsRDFGraph.java
@@ -29,7 +29,7 @@ import org.apache.jena.riot.system.StreamRDF;
 
 /** Use jena to parse data into an CommonsRDF graph */
 public class Ex_ParseIntoCommonsRDFGraph {
-    static { LogCtl.setCmdLogging(); }
+    static { LogCtl.setLogging(); }
 
     public static void main(String ...a) {
         System.out.println("== RDFTermFactoryJena");
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
index 58496bf..0dbea92 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/FusekiLogging.java
@@ -18,16 +18,13 @@
 
 package org.apache.jena.fuseki.system;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
 import java.net.URL;
 import java.nio.file.Path;
 
 import org.apache.jena.atlas.io.IO;
 import org.apache.jena.atlas.lib.StrUtils;
-import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.atlas.logging.LogCmd;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.logging.log4j.core.config.*;
 import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory;
@@ -39,16 +36,22 @@ public class FusekiLogging
     // setLogging is pointless (it's already set).
 
     // Set logging.
-    // 1/ Use system property log4j2.configurationFile if defined.
+    // 1/ Use system property log4j.configurationFile if defined.
     // 2/ Use file:log4j2.properties if exists
     // 3/ Use log4j2.properties on the classpath.
     // 4/ Use org/apache/jena/fuseki/log4j2.properties on the classpath.
     // 5/ Use Built in string
 
-    /** Places for the log4j properties file at (3) */
+    /**
+     * Places for the log4j properties file at (3).
+     * This is not the standard, fixed classpath names used by log4j.  
+     *             //   log4j2.properties, log4j2.yaml, log4j2.json, log4j2.xml
+
+     */
     private static final String[] resourcesForLog4jProperties = {
-        "log4j2.properties",
-        "org/apache/jena/fuseki/log4j2.properties"
+        // NOT the standard, fixed classpath names used by log4j2
+        //  .   log4j2.properties, log4j2.yaml, log4j2.json, log4j2.xml
+        "log4j2-fuseki.properties"
     };
 
     private static final boolean LogLogging     = System.getProperty("fuseki.loglogging") != null;
@@ -95,22 +98,14 @@ public class FusekiLogging
 
         logLogging("Set logging");
         // No loggers have been created but configuration may have been set up.
-        String x = System.getProperty("log4j.configurationFile", null);
-        if ( x == null )
-            logLogging("log4j.configurationFile = <not set>");
-        else
-            logLogging("log4j.configurationFile = %s", x);
-
-        if ( x != null ) {
-            // log4j2 will initialize in the usual way. This includes a value of
-            // "set", which indicates that logging was set before by some other Jena code.
-            if ( x.equals("set") )
-                Fuseki.serverLog.warn("Fuseki logging: Unexpected: Log4j2 was setup by some other part of Jena");
-            return;
+        if ( checkSystemProperties("log4j.configurationFile") ) {
+            logLogging("External log4j2 setup");
+            return ;
         }
+
         logLogging("Setup");
-        // Look for a log4j.properties in the current working directory
-        // and a plane (e.g. FUSEKI_BASE in the webapp/full server) for easy customization.
+        // Look for a log4j.properties file in the current working directory
+        // and a place (e.g. FUSEKI_BASE in the webapp/full server) for easy customization.
         String fn1 = "log4j2.properties";
         String fn2 = null;
 
@@ -121,9 +116,9 @@ public class FusekiLogging
 
         // Try classpath
         for ( String resourceName : resourcesForLog4jProperties ) {
-            // The log4j general initialization is done in a class static
-            // in LogManager so it can't be called again in any sensible manner.
-            // Instead, we include the same basic mechanism ...
+            // In log4j2, classpath initialization is fixed name :
+            //   log4j2.properties, log4j2.yaml, log4j2.json, log4j2.xml
+            // Instead, we manually load a resource.
             logLogging("Try classpath %s", resourceName);
             URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
             if ( url != null ) {
@@ -144,11 +139,26 @@ public class FusekiLogging
         // Use built-in.
         logLogging("Fallback built-in log4j2setup");
         String dftLog4j = log4j2setupFallback();
-        LogCtl.resetLogging(dftLog4j);
+        resetLogging(dftLog4j);
         // Stop anything attempting to do it again.
         System.setProperty(log4j2_configurationFile, "set");
     }
     
+    private static boolean checkSystemProperties(String... properties) {
+        String x = null;
+        for ( String propertyName : properties ) {
+            x = System.getProperty(propertyName, null);
+            if ( x != null ) {
+                if ( "set".equals(x) ) {
+                    Fuseki.serverLog.warn("Fuseki logging: Unexpected: Log4j2 was setup by some other part of Jena");
+                    return true;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
     private static void loadConfiguration(InputStream inputStream, String resourceName) throws IOException {
         ConfigurationSource source = new ConfigurationSource(inputStream);
         ConfigurationFactory factory; 
@@ -161,6 +171,8 @@ public class FusekiLogging
     }
 
     private static boolean attempt(String fn) {
+        if ( fn == null )
+            return false;
         try {
             logLogging("Try file:"+fn);
             File f = new File(fn);
@@ -188,6 +200,7 @@ public class FusekiLogging
     private static String log4j2setupFallback() {
         // This should be the same as resource.
         // It protects against downstream repacking not including all resources.
+        // @formatter:off
         return StrUtils.strjoinNL
             ("## Plain output to stdout"
             , "status = error"
@@ -198,13 +211,14 @@ public class FusekiLogging
             , "filter.threshold.level = INFO"
             , ""
             , "appender.console.type = Console"
-            , "appender.console.name = STDOUT"
+            , "appender.console.name = OUT"
+            , "appender.console.target = SYSTEM_OUT"
             , "appender.console.layout.type = PatternLayout"
             //, "appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-10c{1} %-5p :DFT: %m%n"
             , "appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-10c{1} %-5p %m%n"
             , ""
             , "rootLogger.level                  = INFO"
-            , "rootLogger.appenderRef.stdout.ref = STDOUT"
+            , "rootLogger.appenderRef.stdout.ref = OUT"
             , ""
             , "logger.jena.name  = org.apache.jena"
             , "logger.jena.level = INFO"
@@ -256,6 +270,11 @@ public class FusekiLogging
             , "logger.request-log.level                  = OFF"
             , "logger.request-log.appenderRef.plain.ref  = PLAIN"
                 );
+        // @formatter:on
+    }
+    
+    public static void resetLogging(String configString) {
+        LogCmd.resetLogging(configString);
     }
 }
 
diff --git a/apache-jena/log4j2.properties b/jena-fuseki2/jena-fuseki-main/sparqler/log4j2-console.properties
similarity index 81%
copy from apache-jena/log4j2.properties
copy to jena-fuseki2/jena-fuseki-main/sparqler/log4j2-console.properties
index c5213b5..77b939e 100644
--- a/apache-jena/log4j2.properties
+++ b/jena-fuseki2/jena-fuseki-main/sparqler/log4j2-console.properties
@@ -8,10 +8,16 @@ filter.threshold.level = INFO
 
 appender.console.type = Console
 appender.console.name = OUT
-appender.console.target = SYSTEM_ERR
+appender.console.target = SYSTEM_OUT
 appender.console.layout.type = PatternLayout
-appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
-#appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+#appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
+appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+
+## appender.file.type = File
+## appender.file.name = OUT
+## appender.file.fileName=log.fuseki
+## appender.file.layout.type=PatternLayout
+## appender.file.layout.pattern=[%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
 
 rootLogger.level                  = INFO
 rootLogger.appenderRef.stdout.ref = OUT
diff --git a/apache-jena/log4j2.properties b/jena-fuseki2/jena-fuseki-main/sparqler/log4j2-file.properties
similarity index 77%
copy from apache-jena/log4j2.properties
copy to jena-fuseki2/jena-fuseki-main/sparqler/log4j2-file.properties
index c5213b5..89db576 100644
--- a/apache-jena/log4j2.properties
+++ b/jena-fuseki2/jena-fuseki-main/sparqler/log4j2-file.properties
@@ -6,12 +6,18 @@ filters = threshold
 filter.threshold.type = ThresholdFilter
 filter.threshold.level = INFO
 
-appender.console.type = Console
-appender.console.name = OUT
-appender.console.target = SYSTEM_ERR
-appender.console.layout.type = PatternLayout
-appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
-#appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+## appender.console.type = Console
+## appender.console.name = OUT
+## appender.console.target = SYSTEM_OUT
+## appender.console.layout.type = PatternLayout
+## #appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n
+## appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
+
+appender.file.type = File
+appender.file.name = OUT
+appender.file.fileName=log.fuseki
+appender.file.layout.type=PatternLayout
+appender.file.layout.pattern=[%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n
 
 rootLogger.level                  = INFO
 rootLogger.appenderRef.stdout.ref = OUT
diff --git a/jena-fuseki2/jena-fuseki-main/sparqler/run-sparqler b/jena-fuseki2/jena-fuseki-main/sparqler/run-sparqler
index 0d69faf..3c773f2 100755
--- a/jena-fuseki2/jena-fuseki-main/sparqler/run-sparqler
+++ b/jena-fuseki2/jena-fuseki-main/sparqler/run-sparqler
@@ -26,12 +26,12 @@ fi
 BACKGROUND=${BACKGROUND:-1}
 if [ "$BACKGROUND" = 0 ]
 then
-    LOGCONFIG=${LOGCONFIG:-file:log4j-foreground.properties}
+    LOGCONFIG=${LOGCONFIG:-file:log4j2-console.properties}
 else
-    LOGCONFIG=${LOGCONFIG:-file:log4j-server.properties}
+    LOGCONFIG=${LOGCONFIG:-file:log4j2-file.properties}
 fi
 
-export FUSEKI_LOG="-Dlog4j.configuration=${LOGCONFIG}"
+export FUSEKI_LOG="-Dlog4j.configurationFile=${LOGCONFIG}"
 export JVM_ARGS="${JVM_ARGS:--Xmx1200M}"
 
 ## SPARQLER_ARGS="--base $SPARQLER_PAGES --file=$SPARQLER_DATA  $SPARQLER_DS"
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
index 2521d3b..edb512f 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -205,7 +205,7 @@ public class FusekiServer {
             throw new FusekiException(ex);
         }
         catch (IllegalStateException ex) {
-            throw new FusekiException(ex.getMessage());
+            throw new FusekiException(ex.getMessage(), ex);
         }
         catch (Exception ex) {
             throw new FusekiException(ex);
@@ -1021,12 +1021,12 @@ public class FusekiServer {
             context.addServlet(sh, pathspec);
         }
 
-        private void addFilter(ServletContextHandler context, String pathspec, Filter filter) {
+        private static void addFilter(ServletContextHandler context, String pathspec, Filter filter) {
             FilterHolder holder = new FilterHolder(filter);
             addFilterHolder(context, pathspec, holder);
         }
 
-        private void addFilterHolder(ServletContextHandler context, String pathspec, FilterHolder holder) {
+        private static void addFilterHolder(ServletContextHandler context, String pathspec, FilterHolder holder) {
             context.addFilter(holder, pathspec, null);
         }
 
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExampleService.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExampleService.java
index 0c5fc65..3e76848 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExampleService.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExampleService.java
@@ -20,15 +20,15 @@ package org.apache.jena.fuseki.main.examples;
 
 import java.io.IOException;
 
-import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.fuseki.servlets.ActionREST;
 import org.apache.jena.fuseki.servlets.HttpAction;
 import org.apache.jena.fuseki.servlets.ServletOps;
+import org.apache.jena.fuseki.system.FusekiLogging;
 import org.apache.jena.riot.WebContent;
 import org.apache.jena.web.HttpSC;
 
 public class ExampleService extends ActionREST {
-    static { LogCtl.setLog4j(); }
+    static { FusekiLogging.setLogging(); }
 
     @Override
     protected void doGet(HttpAction action) {
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_1.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_1.java
index 936aa9a..ca8ac99 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_1.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_1.java
@@ -21,13 +21,13 @@ package org.apache.jena.fuseki.main.examples;
 import java.io.IOException;
 
 import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.atlas.web.HttpException;
 import org.apache.jena.atlas.web.TypedInputStream;
 import org.apache.jena.atlas.web.WebLib;
 import org.apache.jena.fuseki.main.FusekiServer;
 import org.apache.jena.fuseki.server.Operation;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.system.FusekiLogging;
 import org.apache.jena.riot.web.HttpOp;
 import org.apache.jena.sparql.core.DatasetGraphFactory;
 import org.apache.jena.util.FileUtils;
@@ -71,7 +71,7 @@ import org.apache.jena.web.HttpSC;
  */
 
 public class ExtendFuseki_AddService_1 {
-    static { LogCtl.setLog4j(); }
+    static { FusekiLogging.setLogging(); }
 
     // Endpoint dispatch only.
 
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_2.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_2.java
index 9900c4a..17ff49e 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_2.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_2.java
@@ -18,13 +18,13 @@
 
 package org.apache.jena.fuseki.main.examples;
 
-import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.atlas.web.WebLib;
 import org.apache.jena.fuseki.build.FusekiConfig;
 import org.apache.jena.fuseki.main.FusekiServer;
 import org.apache.jena.fuseki.server.DataService;
 import org.apache.jena.fuseki.server.Operation;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.system.FusekiLogging;
 import org.apache.jena.query.Query;
 import org.apache.jena.query.QueryExecution;
 import org.apache.jena.query.QueryExecutionFactory;
@@ -41,7 +41,7 @@ import org.apache.jena.web.HttpSC;
  */
 
 public class ExtendFuseki_AddService_2 {
-    static { LogCtl.setLog4j(); }
+    static { FusekiLogging.setLogging(); }
 
     // Endpoint dispatch only.
     static int PORT             = WebLib.choosePort();
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_3.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_3.java
index ba1a047..9560c7e 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_3.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/examples/ExtendFuseki_AddService_3.java
@@ -21,12 +21,12 @@ package org.apache.jena.fuseki.main.examples;
 import java.io.IOException;
 
 import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.atlas.web.TypedInputStream;
 import org.apache.jena.atlas.web.WebLib;
 import org.apache.jena.fuseki.main.FusekiServer;
 import org.apache.jena.fuseki.server.Operation;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.system.FusekiLogging;
 import org.apache.jena.riot.web.HttpOp;
 import org.apache.jena.sparql.core.DatasetGraphFactory;
 import org.apache.jena.util.FileUtils;
@@ -39,7 +39,7 @@ import org.apache.jena.util.FileUtils;
  */
 
 public class ExtendFuseki_AddService_3 {
-    static { LogCtl.setLog4j(); }
+    static { FusekiLogging.setLogging(); }
 
     static int PORT             = WebLib.choosePort();
 
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/resources/log4j2.properties b/jena-fuseki2/jena-fuseki-main/src/test/resources/log4j2.properties
index 02641a0..e181b74 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/resources/log4j2.properties
+++ b/jena-fuseki2/jena-fuseki-main/src/test/resources/log4j2.properties
@@ -8,7 +8,7 @@ filter.threshold.level = INFO
 
 appender.console.type = Console
 appender.console.name = OUT
-appender.console.target = SYSTEM_ERR
+appender.console.target = SYSTEM_OUT
 appender.console.layout.type = PatternLayout
 appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-10c{1} :: %m%n
 #appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-10c{1} :: %m%n
diff --git a/jena-integration-tests/src/test/java/dboe/BaseSoakTest.java b/jena-integration-tests/src/test/java/dboe/BaseSoakTest.java
index 0e6556b..dbec935 100644
--- a/jena-integration-tests/src/test/java/dboe/BaseSoakTest.java
+++ b/jena-integration-tests/src/test/java/dboe/BaseSoakTest.java
@@ -22,13 +22,10 @@ import java.util.List ;
 
 import jena.cmd.CmdException ;
 import jena.cmd.CmdGeneral ;
-
 import org.apache.jena.atlas.lib.Lib ;
 import org.apache.jena.atlas.lib.RandomLib ;
-import org.apache.jena.atlas.logging.LogCtl ;
 
 public abstract class BaseSoakTest extends CmdGeneral {
-    static { LogCtl.setLog4j() ; }
 
     protected final int MinOrder = 2 ;
     protected final int MinSize  = 1 ;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl01_validateGraph.java b/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl01_validateGraph.java
index 6088b0a..36e987b 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl01_validateGraph.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl01_validateGraph.java
@@ -29,7 +29,7 @@ import org.apache.jena.shacl.lib.ShLib;
 
 /** Load shapes and data, validate and print report */
 public class Shacl01_validateGraph {
-    static { LogCtl.setLog4j(); }
+    static { LogCtl.setLogging(); }
 
     public static void main(String ...args) {
         String SHAPES = "shapes.ttl";
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl02_validateTransaction.java b/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl02_validateTransaction.java
index 122dabe..467f807 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl02_validateTransaction.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/examples/Shacl02_validateTransaction.java
@@ -36,7 +36,7 @@ import org.apache.jena.sparql.sse.SSE;
  */
 
 public class Shacl02_validateTransaction {
-    static { LogCtl.setLog4j(); }
+    static { LogCtl.setLogging(); }
 
     public static void main(String...args) {
         String SHAPES = "shapes.ttl";
diff --git a/jena-tdb/src/test/java/org/apache/jena/tdb/base/block/TestBlockMgrMapped.java b/jena-tdb/src/test/java/org/apache/jena/tdb/base/block/TestBlockMgrMapped.java
index 876a981..c1d7f34 100644
--- a/jena-tdb/src/test/java/org/apache/jena/tdb/base/block/TestBlockMgrMapped.java
+++ b/jena-tdb/src/test/java/org/apache/jena/tdb/base/block/TestBlockMgrMapped.java
@@ -19,7 +19,6 @@
 package org.apache.jena.tdb.base.block;
 
 import org.apache.jena.atlas.lib.FileOps ;
-import org.apache.jena.atlas.logging.LogCtl ;
 import org.apache.jena.tdb.ConfigTest ;
 import org.apache.jena.tdb.base.file.BlockAccess ;
 import org.apache.jena.tdb.base.file.BlockAccessMapped ;
@@ -29,10 +28,6 @@ import org.junit.BeforeClass ;
 
 public class TestBlockMgrMapped extends AbstractTestBlockMgr
 {
-    static boolean logging = false ;
-    
-    static { if ( logging ) LogCtl.setLog4j() ; }
-    
     static final String filename = ConfigTest.getTestingDir()+"/block-mgr" ;
     
     // Windows is iffy about deleting memory mapped files.
diff --git a/jena-tdb/src/test/java/org/apache/jena/tdb/index/bplustree/CmdTestBPlusTreeRewriter.java b/jena-tdb/src/test/java/org/apache/jena/tdb/index/bplustree/CmdTestBPlusTreeRewriter.java
index bb94088..8042446 100644
--- a/jena-tdb/src/test/java/org/apache/jena/tdb/index/bplustree/CmdTestBPlusTreeRewriter.java
+++ b/jena-tdb/src/test/java/org/apache/jena/tdb/index/bplustree/CmdTestBPlusTreeRewriter.java
@@ -26,7 +26,7 @@ import org.apache.jena.tdb.sys.SystemTDB ;
 
 public class CmdTestBPlusTreeRewriter
 {
-    static { LogCtl.setLog4j() ; }
+    static { LogCtl.setLogging(); }
     
     public static void main(String...argv)
     {
diff --git a/jena-text/src/main/java/examples/JenaTextExample1.java b/jena-text/src/main/java/examples/JenaTextExample1.java
index 2c0b1e8..8c08d68 100644
--- a/jena-text/src/main/java/examples/JenaTextExample1.java
+++ b/jena-text/src/main/java/examples/JenaTextExample1.java
@@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory ;
 /** Build a text search dataset */
 public class JenaTextExample1
 {
-    static { LogCtl.setLog4j() ; }
+    static { LogCtl.setLogging(); }
     static Logger log = LoggerFactory.getLogger("JenaTextExample") ;
     
     public static void main(String ... argv)