changeset 1454:219f2b937f2b

remove log4j
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 08 Mar 2020 14:11:30 -0600
parents 928be2a4d565
children 1437fb1f0956
files lib/log4j-1.2.17.jar src/goodjava/logger/GoodLoggerFactory.java src/goodjava/logger/ThreadLocalAppender.java src/goodjava/logger/examples/Console.java src/goodjava/logger/examples/LogFile.java src/goodjava/logger/examples/Min.java src/goodjava/logger/examples/RollingFiles.java src/goodjava/logging/Log4jFactory.java src/goodjava/logging/Logger.java src/goodjava/logging/LoggerFactory.java src/goodjava/webserver/examples/Example.java src/luan/Luan.java src/luan/cmd_line.luan src/luan/host/WebHandler.java src/luan/host/init.luan src/luan/modules/ThreadLuan.java src/luan/modules/http/LuanDomainHandler.java src/luan/modules/http/LuanHandler.java src/luan/modules/logging/Log4j.java src/luan/modules/logging/Log4j.luan src/luan/modules/logging/Logging.luan src/luan/modules/logging/LuanLogger.java src/luan/modules/lucene/LuceneIndex.java src/luan/modules/lucene/PostgresBackup.java
diffstat 24 files changed, 272 insertions(+), 274 deletions(-) [+]
line wrap: on
line diff
Binary file lib/log4j-1.2.17.jar has changed
--- a/src/goodjava/logger/GoodLoggerFactory.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/goodjava/logger/GoodLoggerFactory.java	Sun Mar 08 14:11:30 2020 -0600
@@ -7,11 +7,12 @@
 public final class GoodLoggerFactory {
 	private GoodLoggerFactory() {}  // never
 
+	public static final Appender DEFAULT_APPENDER;
 	public static final Configurer DEFAULT_CONFIGURER;
 	static {
 		Layout layout = new ListLayout(Layouts.LEVEL," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE);
-		Appender appender = new ConsoleAppender(layout,System.err);
-		DEFAULT_CONFIGURER = new SimpleConfigurer(Level.INFO,appender);
+		DEFAULT_APPENDER = new ConsoleAppender(layout,System.err);
+		DEFAULT_CONFIGURER = new SimpleConfigurer(Level.INFO,DEFAULT_APPENDER);
 	}
 	private static final Map<String,GoodLogger> map = new HashMap<String,GoodLogger>();
 	private static Configurer configurer = DEFAULT_CONFIGURER;
--- a/src/goodjava/logger/ThreadLocalAppender.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/goodjava/logger/ThreadLocalAppender.java	Sun Mar 08 14:11:30 2020 -0600
@@ -2,7 +2,7 @@
 
 
 public final class ThreadLocalAppender implements Appender {
-	private final Appender defaultAppender;
+	public volatile Appender defaultAppender;
 	public final ThreadLocal<Appender> threadLocal = new ThreadLocal<Appender>();
 
 	public ThreadLocalAppender(Appender defaultAppender) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/goodjava/logger/examples/Console.java	Sun Mar 08 14:11:30 2020 -0600
@@ -0,0 +1,32 @@
+package goodjava.logger.examples;
+
+import goodjava.logging.Logger;
+import goodjava.logging.LoggerFactory;
+import goodjava.logger.Layout;
+import goodjava.logger.Layouts;
+import goodjava.logger.DateLayout;
+import goodjava.logger.ListLayout;
+import goodjava.logger.Appender;
+import goodjava.logger.ConsoleAppender;
+import goodjava.logger.Level;
+import goodjava.logger.SimpleConfigurer;
+import goodjava.logger.GoodLoggerFactory;
+
+
+public class Console {
+	private static final Logger logger = LoggerFactory.getLogger(Console.class);
+
+	public static void main(String[] args) {
+		config();
+		logger.debug("test debug");
+		logger.info("test info");
+		logger.warn("test warn");
+		logger.error("test error");
+	}
+
+	static void config() {
+		Layout layout = new ListLayout(new DateLayout("yyyy-MM-dd HH:mm:ss,SSS")," ",Layouts.LEVEL_PADDED," ",Layouts.LOGGER," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE);
+		Appender appender = new ConsoleAppender(layout,System.err);
+		GoodLoggerFactory.setConfigurer( new SimpleConfigurer(Level.INFO,appender) );
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/goodjava/logger/examples/LogFile.java	Sun Mar 08 14:11:30 2020 -0600
@@ -0,0 +1,34 @@
+package goodjava.logger.examples;
+
+import goodjava.logging.Logger;
+import goodjava.logging.LoggerFactory;
+import goodjava.logger.Layout;
+import goodjava.logger.Layouts;
+import goodjava.logger.DateLayout;
+import goodjava.logger.ListLayout;
+import goodjava.logger.Appender;
+import goodjava.logger.WriterAppender;
+import goodjava.logger.Level;
+import goodjava.logger.SimpleConfigurer;
+import goodjava.logger.GoodLoggerFactory;
+import java.io.FileWriter;
+import java.io.IOException;
+
+
+public class LogFile {
+	private static final Logger logger = LoggerFactory.getLogger(LogFile.class);
+
+	public static void main(String[] args) throws Exception {
+		config();
+		logger.debug("test debug");
+		logger.info("test info");
+		logger.warn("test warn");
+		logger.error("test error");
+	}
+
+	static void config() throws IOException {
+		Layout layout = new ListLayout(new DateLayout("yyyy-MM-dd HH:mm:ss,SSS")," ",Layouts.LEVEL_PADDED," ",Layouts.LOGGER," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE);
+		Appender appender = new WriterAppender(layout,new FileWriter("test.log",true));
+		GoodLoggerFactory.setConfigurer( new SimpleConfigurer(Level.INFO,appender) );
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/goodjava/logger/examples/Min.java	Sun Mar 08 14:11:30 2020 -0600
@@ -0,0 +1,16 @@
+package goodjava.logger.examples;
+
+import goodjava.logging.Logger;
+import goodjava.logging.LoggerFactory;
+
+
+public class Min {
+	private static final Logger logger = LoggerFactory.getLogger(Min.class);
+
+	public static void main(String[] args) {
+		logger.debug("test debug");
+		logger.info("test info");
+		logger.warn("test warn");
+		logger.error("test error");
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/goodjava/logger/examples/RollingFiles.java	Sun Mar 08 14:11:30 2020 -0600
@@ -0,0 +1,43 @@
+package goodjava.logger.examples;
+
+import goodjava.logging.Logger;
+import goodjava.logging.LoggerFactory;
+import goodjava.logger.Layout;
+import goodjava.logger.Layouts;
+import goodjava.logger.DateLayout;
+import goodjava.logger.ListLayout;
+import goodjava.logger.Appender;
+import goodjava.logger.RollingFileAppender;
+import goodjava.logger.LevelAppender;
+import goodjava.logger.ListAppender;
+import goodjava.logger.Level;
+import goodjava.logger.SimpleConfigurer;
+import goodjava.logger.GoodLoggerFactory;
+import java.io.IOException;
+
+
+public class RollingFiles {
+	private static final Logger logger = LoggerFactory.getLogger(RollingFiles.class);
+
+	public static void main(String[] args) throws Exception {
+		config();
+		logger.debug("test debug");
+		logger.info("test info");
+		logger.warn("test warn");
+		logger.error("test error");
+	}
+
+	static void config() throws IOException {
+		Layout layout = new ListLayout(new DateLayout("yyyy-MM-dd HH:mm:ss,SSS")," ",Layouts.LEVEL_PADDED," ",Layouts.LOGGER," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE);
+		Appender error = appender(layout,"error.log",Level.ERROR);
+		Appender warn = appender(layout,"warn.log",Level.WARN);
+		Appender info = appender(layout,"info.log",Level.INFO);
+		Appender appender = new ListAppender(error,warn,info);
+		GoodLoggerFactory.setConfigurer( new SimpleConfigurer(Level.INFO,appender) );
+	}
+
+	static Appender appender(Layout layout,String fileName,int level) throws IOException {
+		RollingFileAppender appender = new RollingFileAppender(layout,fileName);
+		return new LevelAppender(appender,level);
+	}
+}
--- a/src/goodjava/logging/Log4jFactory.java	Mon Mar 02 15:09:10 2020 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-package goodjava.logging;
-
-
-public final class Log4jFactory implements ILoggerFactory {
-	private static final class Log4jLogger implements Logger {
-		final org.apache.log4j.Logger log4j;
-
-		Log4jLogger(org.apache.log4j.Logger log4j) {
-			this.log4j = log4j;
-		}
-
-		@Override public void error(String msg) {
-			log4j.error(msg);
-		}
-
-		@Override public void error(String msg,Throwable t) {
-			log4j.error(msg,t);
-		}
-
-		@Override public void warn(String msg) {
-			log4j.warn(msg);
-		}
-
-		@Override public void warn(String msg,Throwable t) {
-			log4j.warn(msg,t);
-		}
-
-		@Override public void info(String msg) {
-			log4j.info(msg);
-		}
-
-		@Override public void info(String msg,Throwable t) {
-			log4j.info(msg,t);
-		}
-
-		@Override public boolean isInfoEnabled() {
-			return log4j.isInfoEnabled();
-		}
-
-		@Override public void debug(String msg) {
-			log4j.debug(msg);
-		}
-
-		@Override public void debug(String msg,Throwable t) {
-			log4j.debug(msg,t);
-		}
-
-		@Override public boolean isDebugEnabled() {
-			return log4j.isDebugEnabled();
-		}
-	}
-
-	@Override public Logger getLogger(String name) {
-		return new Log4jLogger(org.apache.log4j.Logger.getLogger(name));
-	}
-}
--- a/src/goodjava/logging/Logger.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/goodjava/logging/Logger.java	Sun Mar 08 14:11:30 2020 -0600
@@ -1,6 +1,5 @@
 package goodjava.logging;
 
-// Because slf4j is an overcomplicated mess that caches loggers when it shouldn't.
 
 public interface Logger {
 	public void error(String msg);
--- a/src/goodjava/logging/LoggerFactory.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/goodjava/logging/LoggerFactory.java	Sun Mar 08 14:11:30 2020 -0600
@@ -4,7 +4,7 @@
 public final class LoggerFactory {
 	public static final ILoggerFactory implementation;
 	static {
-		String s = System.getProperty("goodjava.logger","goodjava.logging.Log4jFactory");
+		String s = System.getProperty("goodjava.logger","goodjava.logger.LoggingFactory");
 		try {
 			implementation = (ILoggerFactory)Class.forName(s).newInstance();
 		} catch(ClassNotFoundException e) {
--- a/src/goodjava/webserver/examples/Example.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/goodjava/webserver/examples/Example.java	Sun Mar 08 14:11:30 2020 -0600
@@ -5,9 +5,6 @@
 import java.io.IOException;
 import java.util.Map;
 import java.util.HashMap;
-import org.apache.log4j.EnhancedPatternLayout;
-import org.apache.log4j.ConsoleAppender;
-import org.apache.log4j.Logger;
 import goodjava.webserver.Handler;
 import goodjava.webserver.Request;
 import goodjava.webserver.Response;
@@ -58,15 +55,7 @@
 		new Server(8080,handler).start();
 	}
 
-	public static void initLogging() {
-//		Logger.getRootLogger().setLevel(Level.INFO);
-		EnhancedPatternLayout layout = new EnhancedPatternLayout("%d{HH:mm:ss} %-5p %c - %m%n");
-		ConsoleAppender appender = new ConsoleAppender(layout,"System.err");
-		Logger.getRootLogger().addAppender(appender);
-	}
-
 	public static void main(String[] args) throws Exception {
-		initLogging();
 		fancy();
 	}
 }
--- a/src/luan/Luan.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/Luan.java	Sun Mar 08 14:11:30 2020 -0600
@@ -1,6 +1,6 @@
 package luan;
 
-import java.lang.reflect.Array;
+import java.lang.reflect.Array;
 import java.io.IOException;
 import java.util.List;
 import java.util.ArrayList;
@@ -163,31 +163,27 @@
 		return null;
 	}
 
-	public Logger getLogger(Class cls) {
-		return LuanLogger.getLogger(this,cls);
-	}
-
 
 
 	// static
 
 	public static void main(String[] args) throws LuanException {
-		Luan luan = new Luan();
+		Luan luan = new Luan();
 		LuanFunction fn = loadClasspath(luan,"luan/cmd_line.luan");
 		fn.call((Object[])args);
 	}
-
-	public static LuanFunction loadClasspath(Luan luan,String classpath)
-		throws LuanException
-	{
+
+	public static LuanFunction loadClasspath(Luan luan,String classpath)
+		throws LuanException
+	{
 		try {
-			String src = IoLuan.classpath(luan,classpath).read_text();
-			return luan.load(src,"classpath:"+classpath,true);
-		} catch(IOException e) {
-			throw new RuntimeException(e);
+			String src = IoLuan.classpath(luan,classpath).read_text();
+			return luan.load(src,"classpath:"+classpath,true);
+		} catch(IOException e) {
+			throw new RuntimeException(e);
 		}
 	}
-
+
 	public static Object first(Object obj) {
 		if( !(obj instanceof Object[]) )
 			return obj;
--- a/src/luan/cmd_line.luan	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/cmd_line.luan	Sun Mar 08 14:11:30 2020 -0600
@@ -8,7 +8,6 @@
 local unpack = Table.unpack or error()
 local Io = require "luan:Io.luan"
 local print = Io.print or error()
-local Logging = require "luan:logging/Logging.luan"
 
 
 local args = {...}
--- a/src/luan/host/WebHandler.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/host/WebHandler.java	Sun Mar 08 14:11:30 2020 -0600
@@ -14,7 +14,7 @@
 import luan.LuanClosure;
 import luan.LuanRuntimeException;
 import luan.modules.http.LuanHandler;
-import luan.modules.logging.Log4j;
+import luan.modules.logging.LuanLogger;
 
 
 public class WebHandler implements Handler {
@@ -31,7 +31,6 @@
 			new File(logDir).mkdirs();
 
 			Luan luan = new Luan();
-			Log4j.newLoggerRepository(luan);
 			initLuan(luan,dirStr,domain);
 			return new LuanHandler(luan,domain);
 		}
@@ -47,6 +46,7 @@
 		if( !new File(dir).exists() )
 			throw new RuntimeException();
 		sitesDir = dir;
+		LuanLogger.initThreadLogging();
 	}
 
 	@Override public Response handle(Request request) {
@@ -59,11 +59,14 @@
 	}
 
 	private static void initLuan(Luan luan,String dir,String domain) {
+		LuanLogger.startThreadLogging(luan);
 		try {
 			LuanFunction fn = Luan.loadClasspath(luan,"luan/host/init.luan");
 			fn.call(dir,domain);
 		} catch(LuanException e) {
 			throw new LuanRuntimeException(e);
+		} finally {
+			LuanLogger.endThreadLogging();
 		}
 		security(luan,dir);
 	}
--- a/src/luan/host/init.luan	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/host/init.luan	Sun Mar 08 14:11:30 2020 -0600
@@ -3,6 +3,8 @@
 local do_file = Luan.do_file or error()
 local String = require "luan:String.luan"
 local gsub = String.gsub or error()
+local Number = require "luan:Number.luan"
+local long = Number.long or error()
 
 
 local dir, domain = ...
@@ -10,30 +12,34 @@
 
 -- logging
 
+local one_mb = long(1024*1024)
+
 do
 	require "java"
-	local Log4j = require "java:luan.modules.logging.Log4j"
-	local Level = require "java:org.apache.log4j.Level"
-	local EnhancedPatternLayout = require "java:org.apache.log4j.EnhancedPatternLayout"
-	local RollingFileAppender = require "java:org.apache.log4j.RollingFileAppender"
+	local LuanLogger = require "java:luan.modules.logging.LuanLogger"
+	local Layouts = require "java:goodjava.logger.Layouts"
+	local DateLayout = require "java:goodjava.logger.DateLayout"
+	local ListLayout = require "java:goodjava.logger.ListLayout"
+	local Level = require "java:goodjava.logger.Level"
+	local RollingFileAppender = require "java:goodjava.logger.RollingFileAppender"
+	local LevelAppender = require "java:goodjava.logger.LevelAppender"
+	local ListAppender = require "java:goodjava.logger.ListAppender"
 
-	local logger = Log4j.getRootLogger()
-	Log4j.removeAllAppenders(logger)
-	local layout = EnhancedPatternLayout.new("%d %-5p %c - %m%n")
+	local layout = ListLayout.new(DateLayout.new("yyyy-MM-dd HH:mm:ss,SSS")," ",Layouts.LEVEL_PADDED," ",Layouts.LOGGER," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE)
 	local log_dir = dir.."/site/private/local/logs/"
 
-	local function add_appender(file,level)
+	local function new_appender(file,level)
 		local appender = RollingFileAppender.new(layout, log_dir..file)
-		appender.setMaxFileSize("1MB")
-		logger.addAppender(appender)
-		if level ~= logger.getEffectiveLevel() then
-			appender.setThreshold(level)
-		end
+		appender.maxFileSize = one_mb
+		appender = LevelAppender.new(appender,level)
+		return appender
 	end
 
-	add_appender("error.log",Level.ERROR)
-	add_appender("warn.log",Level.WARN)
-	add_appender("info.log",Level.INFO)
+	local err = new_appender("error.log",Level.ERROR)
+	local warn = new_appender("warn.log",Level.WARN)
+	local info = new_appender("info.log",Level.INFO)
+	local appender = ListAppender.new(err,warn,info)
+	LuanLogger.configure(appender)
 end
 
 
--- a/src/luan/modules/ThreadLuan.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/ThreadLuan.java	Sun Mar 08 14:11:30 2020 -0600
@@ -24,6 +24,7 @@
 import luan.LuanException;
 import luan.LuanCloner;
 import luan.LuanCloneable;
+import luan.modules.logging.LuanLogger;
 import goodjava.logging.Logger;
 import goodjava.logging.LoggerFactory;
 
@@ -37,10 +38,13 @@
 	private static Runnable runnable(final LuanFunction fn) {
 		return new Runnable() {
 			public synchronized void run() {
+				LuanLogger.startThreadLogging(fn.luan());
 				try {
 					fn.call();
 				} catch(LuanException e) {
 					e.printStackTrace();
+				} finally {
+					LuanLogger.endThreadLogging();
 				}
 			}
 		};
--- a/src/luan/modules/http/LuanDomainHandler.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/http/LuanDomainHandler.java	Sun Mar 08 14:11:30 2020 -0600
@@ -9,7 +9,7 @@
 import luan.LuanCloner;
 import luan.LuanFunction;
 import luan.LuanException;
-import luan.modules.logging.Log4j;
+import luan.modules.logging.LuanLogger;
 
 
 public class LuanDomainHandler implements Handler, DomainHandler.Factory {
@@ -18,6 +18,7 @@
 	private final DomainHandler domainHandler = new DomainHandler(this);
 
 	public LuanDomainHandler(Luan luanInit) {
+		LuanLogger.initThreadLogging();
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		this.luanInit = (Luan)cloner.clone(luanInit);
 	}
@@ -27,14 +28,9 @@
 		return new LuanHandler(luan,domain);
 	}
 
-	protected void newLoggerRepository(Luan luan) {
-		Log4j.newLoggerRepository(luan);
-	}
-
 	protected Luan newLuan(final String domain) {
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		Luan luan = (Luan)cloner.clone(luanInit);
-		newLoggerRepository(luan);
 		LuanFunction reset_luan = new LuanFunction(false) {
 			@Override public Object call(Object[] args) {
 				domainHandler.removeHandler(domain);
--- a/src/luan/modules/http/LuanHandler.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/http/LuanHandler.java	Sun Mar 08 14:11:30 2020 -0600
@@ -35,13 +35,12 @@
 
 
 public final class LuanHandler implements Handler, Closeable {
-	private static final Logger sysLogger = LoggerFactory.getLogger(LuanHandler.class);
+	private static final Logger logger = LoggerFactory.getLogger(LuanHandler.class);
 
 	private static final Set<LuanHandler> dontGc = Collections.newSetFromMap(new ConcurrentHashMap<LuanHandler,Boolean>());
 
 	private final Luan luanInit;
 	private final String domain;
-	private final Logger luanLogger;
 	private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
 	private volatile Luan currentLuan;
 	private volatile boolean isDisabled = false;
@@ -64,7 +63,6 @@
 	public LuanHandler(Luan luanInit,String domain) {
 		this.luanInit = luanInit;
 		this.domain = domain;
-		this.luanLogger = luanInit.getLogger(LuanHandler.class);
 		try {
 			Fns fns = new Fns(this);
 			LuanTable Http = (LuanTable)luanInit.require("luan:http/Http.luan");
@@ -77,13 +75,13 @@
 			throw new RuntimeException(e);
 		}
 		if( domain != null )
-			sysLogger.info("new "+domain);
+			logger.info("new "+domain);
 		currentLuan = newLuan();
 	}
 
 	protected void finalize() throws Throwable {
 		if( domain != null )
-			sysLogger.info("gc "+domain);
+			logger.info("gc "+domain);
 	}
 
 	private Luan newLuan() {
@@ -92,21 +90,19 @@
 			LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 			luan = (Luan)cloner.clone(luanInit);
 		}
+		LuanLogger.startThreadLogging(luan);
 		try {
 			PackageLuan.load(luan,"site:/init.luan");
 		} catch(LuanException e) {
 			//e.printStackTrace();
 			String err = e.getLuanStackTraceString();
-			luanLogger.error(err);
+			logger.error(err);
+		} finally {
+			LuanLogger.endThreadLogging();
 		}
 		return luan;
 	}
 
-/*
-	public Luan getLuan() {
-		return luan;
-	}
-*/
 	static final String NOT_FOUND = "luan-not-found";
 
 	@Override public Response handle(Request request) {
@@ -122,14 +118,16 @@
 		String oldName = thread.getName();
 		thread.setName(request.headers.get("host")+request.path);
 		rwLock.readLock().lock();
+		LuanLogger.startThreadLogging(currentLuan);
 		try {
 			return service(request,notFound);
 		} catch(LuanException e) {
 			String err = e.getLuanStackTraceString();
-			luanLogger.error(err+"\n"+request.rawHead.trim()+"\n");
+			logger.error(err+"\n"+request.rawHead.trim()+"\n");
 			String msg = "Internel Server Error\n\n" + err;
 			return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg );
 		} finally {
+			LuanLogger.endThreadLogging();
 			rwLock.readLock().unlock();
 			thread.setName(oldName);
 		}
@@ -137,11 +135,12 @@
 
 	public void close() {
 		Object obj = dontGc.remove(this);
-		//sysLogger.info("close "+domain+" "+(obj!=null));
+		//logger.info("close "+domain+" "+(obj!=null));
 	}
 
 	public Object call_rpc(String fnName,Object... args) throws LuanException {
 		rwLock.readLock().lock();
+		LuanLogger.startThreadLogging(currentLuan);
 		try {
 			LuanFunction fn;
 			synchronized(luanInit) {
@@ -156,6 +155,7 @@
 			}
 			return fn.call(args);
 		} finally {
+			LuanLogger.endThreadLogging();
 			rwLock.readLock().unlock();
 		}
 	}
@@ -196,7 +196,7 @@
 
 	private void dont_gc() {
 		dontGc.add(this);
-		//sysLogger.info("dont_gc "+domain);
+		//logger.info("dont_gc "+domain);
 	}
 
 	public static final class Fns {
--- a/src/luan/modules/logging/Log4j.java	Mon Mar 02 15:09:10 2020 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-package luan.modules.logging;
-
-import java.util.Enumeration;
-import java.util.List;
-import java.util.ArrayList;
-import org.apache.log4j.Logger;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Hierarchy;
-import org.apache.log4j.Level;
-import org.apache.log4j.Appender;
-import org.apache.log4j.spi.LoggerRepository;
-import org.apache.log4j.spi.RootLogger;
-import org.apache.log4j.spi.RepositorySelector;
-import luan.Luan;
-import luan.LuanException;
-import luan.LuanTable;
-
-
-public final class Log4j {
-	private static final String KEY = "Logger.Repository";
-	private static final LoggerRepository defaultLoggerRepository = LogManager.getLoggerRepository();
-
-	public static void newLoggerRepository(Luan luan) {
-		Logger oldLogger = defaultLoggerRepository.getRootLogger();
-		Logger newLogger = new RootLogger(Level.DEBUG);
-		LoggerRepository lr = new Hierarchy(newLogger);
-		for( Enumeration en = oldLogger.getAllAppenders(); en.hasMoreElements(); ) {
-			Appender appender = (Appender)en.nextElement();
-			newLogger.addAppender(appender);
-		}
-		luan.registry().put(KEY,lr);
-	}
-
-	private static LoggerRepository getLoggerRepository(Luan luan) {
-		LoggerRepository lr = (LoggerRepository)luan.registry().get(KEY);
-		return lr != null ? lr : defaultLoggerRepository;
-	}
-
-	static {
-		LogManager.setRepositorySelector( new RepositorySelector() {
-			public LoggerRepository getLoggerRepository() {
-				Luan luan = LuanLogger.luan();
-				return luan==null ? defaultLoggerRepository : Log4j.getLoggerRepository(luan);
-			}
-		}, new Object() );
-	}
-
-	public static Logger getRootLogger(Luan luan) {
-		return getLoggerRepository(luan).getRootLogger();
-	}
-
-	public static Logger getLogger(Luan luan,String name) {
-		return getLoggerRepository(luan).getLogger(name);
-	}
-
-	// because logger.removeAllAppenders() closes the appenders
-	public static void removeAllAppenders(Logger logger) {
-		List<Appender> list = new ArrayList<Appender>();
-		for( Enumeration en = logger.getAllAppenders(); en.hasMoreElements(); ) {
-			Appender appender = (Appender)en.nextElement();
-			list.add(appender);
-		}
-		for( Appender appender : list ) {
-			logger.removeAppender(appender);
-		}
-		if( logger.getAllAppenders().hasMoreElements() )
-			throw new RuntimeException();
-	}
-}
--- a/src/luan/modules/logging/Log4j.luan	Mon Mar 02 15:09:10 2020 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-require "java"
-local JavaLog4j = require "java:luan.modules.logging.Log4j"
-local EnhancedPatternLayout = require "java:org.apache.log4j.EnhancedPatternLayout"
-local ConsoleAppender = require "java:org.apache.log4j.ConsoleAppender"
-local Level = require "java:org.apache.log4j.Level"
-
-
-local Log4j = {}
-
-function Log4j.init_root()
-	local root = JavaLog4j.getRootLogger()
-	local has_appenders = root.getAllAppenders().hasMoreElements()
-	if not has_appenders then
---		root.setLevel(Level.INFO)
-		local layout = EnhancedPatternLayout.new("%d %-5p %c - %m%n")
-		local appender = ConsoleAppender.new(layout,"System.err");
-		root.addAppender(appender);
-	end
-end
-Log4j.init_root()
-
-return Log4j
--- a/src/luan/modules/logging/Logging.luan	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/logging/Logging.luan	Sun Mar 08 14:11:30 2020 -0600
@@ -1,9 +1,16 @@
 require "java"
 local LuanLogger = require "java:luan.modules.logging.LuanLogger"
 
-local Package = require "luan:Package.luan"
-if Package.load("java:org.apache.log4j.Logger") ~= false then
-	require "luan:logging/Log4j.luan"
+if not LuanLogger.isConfigured() then
+	local System = require "java:java.lang.System"
+	local Layouts = require "java:goodjava.logger.Layouts"
+	local DateLayout = require "java:goodjava.logger.DateLayout"
+	local ListLayout = require "java:goodjava.logger.ListLayout"
+	local ConsoleAppender = require "java:goodjava.logger.ConsoleAppender"
+
+	local layout = ListLayout.new(DateLayout.new("yyyy-MM-dd HH:mm:ss,SSS")," ",Layouts.LEVEL_PADDED," ",Layouts.LOGGER," - ",Layouts.MESSAGE,"\n",Layouts.THROWABLE)
+	local appender = ConsoleAppender.new(layout,System.err)
+	LuanLogger.configure(appender)
 end
 
 
--- a/src/luan/modules/logging/LuanLogger.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/logging/LuanLogger.java	Sun Mar 08 14:11:30 2020 -0600
@@ -2,6 +2,12 @@
 
 import goodjava.logging.Logger;
 import goodjava.logging.LoggerFactory;
+import goodjava.logger.LoggingFactory;
+import goodjava.logger.GoodLoggerFactory;
+import goodjava.logger.Appender;
+import goodjava.logger.ThreadLocalAppender;
+import goodjava.logger.SimpleConfigurer;
+import goodjava.logger.Level;
 import luan.Luan;
 import luan.LuanException;
 
@@ -9,8 +15,8 @@
 public final class LuanLogger {
 	private final Logger logger;
 
-	public LuanLogger(Luan luan,String name) {
-		this.logger = getLogger(luan,name);
+	public LuanLogger(String name) {
+		this.logger = LoggerFactory.getLogger(name);
 	}
 
 	public void error(Object obj) throws LuanException {
@@ -30,37 +36,58 @@
 	}
 
 
-	private static ThreadLocal<Luan> tl = new ThreadLocal<Luan>();
+	private static final String KEY = "Logger.Appender";
+	private static volatile Appender globalAppender = GoodLoggerFactory.DEFAULT_APPENDER;
 
-	private static void init(Luan luan) {
-		try {
-			luan.require("luan:logging/Logging.luan");  // ensure initialization
-		} catch(LuanException e) {
-			throw new RuntimeException(e);
+	public static synchronized void initThreadLogging() {
+		if( !(globalAppender instanceof ThreadLocalAppender) ) {
+			if( !(LoggerFactory.implementation instanceof LoggingFactory) )
+				throw new RuntimeException("must use goodjava.logger for thread logging");
+			globalAppender = new ThreadLocalAppender(globalAppender);
+			configure();
 		}
 	}
 
-	public static Logger getLogger(Luan luan,String name) {
-		init(luan);
-		tl.set(luan);
-		try {
-			return LoggerFactory.getLogger(name);
-		} finally {
-			tl.remove();
+	public static void startThreadLogging(Luan luan) {
+		if( !(globalAppender instanceof ThreadLocalAppender) )
+			return;
+		ThreadLocalAppender tla = (ThreadLocalAppender)globalAppender;
+		Appender appender = (Appender)luan.registry().get(KEY);
+		if( appender == null )
+			appender = tla.defaultAppender;
+		tla.threadLocal.set(appender);
+	}
+
+	public static void endThreadLogging() {
+		if( !(globalAppender instanceof ThreadLocalAppender) )
+			return;
+		ThreadLocalAppender tla = (ThreadLocalAppender)globalAppender;
+		tla.threadLocal.remove();
+	}
+
+	public static boolean isConfigured() {
+		if( !(LoggerFactory.implementation instanceof LoggingFactory) )
+			return true;
+		return GoodLoggerFactory.getConfigurer() != GoodLoggerFactory.DEFAULT_CONFIGURER;
+	}
+
+	public static void configure(Luan luan,Appender appender) {
+		if( globalAppender instanceof ThreadLocalAppender ) {
+			ThreadLocalAppender tla = (ThreadLocalAppender)globalAppender;
+			if( tla.threadLocal.get() != null ) {
+				luan.registry().put(KEY,appender);
+				tla.threadLocal.set(appender);
+			} else {
+				tla.defaultAppender = appender;
+			}
+		} else {
+			globalAppender = appender;
+			configure();
 		}
 	}
 
-	public static Logger getLogger(Luan luan,Class cls) {
-		init(luan);
-		tl.set(luan);
-		try {
-			return LoggerFactory.getLogger(cls);
-		} finally {
-			tl.remove();
-		}
+	private static void configure() {
+		GoodLoggerFactory.setConfigurer( new SimpleConfigurer(Level.INFO,globalAppender) );
 	}
 
-	public static Luan luan() {
-		return tl.get();
-	}
 }
--- a/src/luan/modules/lucene/LuceneIndex.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/lucene/LuceneIndex.java	Sun Mar 08 14:11:30 2020 -0600
@@ -86,7 +86,7 @@
 
 
 public final class LuceneIndex {
-	private static final Logger sysLogger = LoggerFactory.getLogger(LuceneIndex.class);
+	private static final Logger logger = LoggerFactory.getLogger(LuceneIndex.class);
 
 	private static Map<String,Reference<LuceneIndex>> indexes = new HashMap<String,Reference<LuceneIndex>>();
 
@@ -116,7 +116,6 @@
 	public static final StringFieldParser STRING_FIELD_PARSER = new StringFieldParser(new KeywordAnalyzer());
 	public static final StringFieldParser ENGLISH_FIELD_PARSER = new StringFieldParser(new EnglishAnalyzer(luceneVersion));
 
-	private final Logger luanLogger;
 	private final Object version;
 
 	private final ReentrantLock writeLock = new ReentrantLock();
@@ -151,7 +150,6 @@
 		LuanTable postgresSpec = Utils.removeTable(options,"postgres_spec");
 		Utils.checkEmpty(options);
 
-		this.luanLogger = luan.getLogger(LuceneIndex.class);
 //		this.defaultFieldParser = defaultFieldParser;
 //		this.defaultFields = defaultFields;
 		mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields);
@@ -170,11 +168,11 @@
 		} else {
 			postgresBackup = new PostgresBackup(luan,postgresSpec);
 			if( !wasCreated && postgresBackup.wasCreated ) {
-				luanLogger.error("rebuilding postgres backup");
+				logger.error("rebuilding postgres backup");
 				rebuild_postgres_backup(luan);
 /*
 			} else if( wasCreated && !postgresBackup.wasCreated ) {
-				luanLogger.error("restoring from postgres");
+				logger.error("restoring from postgres");
 				restore_from_postgres();
 */
 			}
@@ -806,7 +804,7 @@
 	public void rebuild_postgres_backup(Luan luan)
 		throws IOException, LuanException, SQLException
 	{
-		luanLogger.info("start rebuild_postgres_backup");
+		logger.info("start rebuild_postgres_backup");
 		writeLock.lock();
 		IndexSearcher searcher = openSearcher();
 		boolean ok = false;
@@ -840,14 +838,14 @@
 				postgresBackup.rollback();
 			writeLock.unlock();
 		}
-		luanLogger.info("end rebuild_postgres_backup");
+		logger.info("end rebuild_postgres_backup");
 	}
 
 	public void restore_from_postgres(LuanFunction completer)
 		throws IOException, LuanException, SQLException, ParseException
 	{
 		if( postgresBackup!=null && wasCreated && !postgresBackup.wasCreated ) {
-			luanLogger.error("restoring from postgres");
+			logger.error("restoring from postgres");
 			force_restore_from_postgres(completer);
 		}
 	}
@@ -855,7 +853,7 @@
 	public void force_restore_from_postgres(LuanFunction completer)
 		throws IOException, LuanException, SQLException, ParseException
 	{
-		luanLogger.warn("start restore_from_postgres");
+		logger.warn("start restore_from_postgres");
 		if( postgresBackup==null )
 			throw new NullPointerException();
 		if( writeLock.isHeldByCurrentThread() )
@@ -879,7 +877,7 @@
 			wrote();
 			writeLock.unlock();
 		}
-		luanLogger.warn("end restore_from_postgres");
+		logger.warn("end restore_from_postgres");
 	}
 
 	void restore(LuanFunction completer,LuanTable doc)
@@ -893,19 +891,19 @@
 		String msg = "start check";
 		if( hasPostgres )
 			msg += " with postgres";
-		luanLogger.info(msg);
+		logger.info(msg);
 		CheckIndex.Status status = new CheckIndex(fsDir).checkIndex();
 		if( !status.clean )
-			luanLogger.error("index not clean");
+			logger.error("index not clean");
 		if( hasPostgres )
 			checkPostgres(luan);
-		luanLogger.info("end check");
+		logger.info("end check");
 	}
 
 	private void checkPostgres(Luan luan)
 		throws IOException, SQLException, LuanException, ParseException
 	{
-		//luanLogger.info("start postgres check");
+		//logger.info("start postgres check");
 		final PostgresBackup.Checker postgresChecker = postgresBackup.newChecker();
 		final IndexSearcher searcher = openSearcher();
 		try {
@@ -967,7 +965,7 @@
 	private void checkPostgres(Luan luan,PostgresBackup.Checker postgresChecker,LuanToString lts,long id)
 		throws IOException, SQLException, LuanException, ParseException
 	{
-		//luanLogger.info("check id "+id);
+		//logger.info("check id "+id);
 		writeLock.lock();
 		try {
 			final IndexSearcher searcher = openSearcher();
@@ -984,17 +982,17 @@
 					throw new RuntimeException();
 				if( docPostgres == null ) {
 					if( docLucene != null )
-						luanLogger.error("id "+id+" found in lucene but not postgres");
+						logger.error("id "+id+" found in lucene but not postgres");
 					return;
 				}
 				if( docLucene == null ) {
-					luanLogger.error("id "+id+" found in postgres but not lucene");
+					logger.error("id "+id+" found in postgres but not lucene");
 					return;
 				}
 				if( !equal(docPostgres,docLucene) ) {
-					luanLogger.error("id "+id+" not equal");
-					luanLogger.error("lucene = "+lts.toString(docLucene));
-					luanLogger.error("postgres = "+lts.toString(docPostgres));
+					logger.error("id "+id+" not equal");
+					logger.error("lucene = "+lts.toString(docLucene));
+					logger.error("postgres = "+lts.toString(docPostgres));
 				}
 			} finally {
 				close(searcher);
@@ -1016,7 +1014,7 @@
 			if( value instanceof LuanTable ) {
 				LuanTable v = (LuanTable)value;
 				if( !v.isList() )
-					sysLogger.error("not list");
+					logger.error("not list");
 				entry.setValue(v.asList());
 			}
 		}
--- a/src/luan/modules/lucene/PostgresBackup.java	Mon Mar 02 15:09:10 2020 -0700
+++ b/src/luan/modules/lucene/PostgresBackup.java	Sun Mar 08 14:11:30 2020 -0600
@@ -24,9 +24,7 @@
 
 
 final class PostgresBackup {
-	private static final Logger sysLogger = LoggerFactory.getLogger(PostgresBackup.class);
-
-	private final Logger luanLogger;
+	private static final Logger logger = LoggerFactory.getLogger(PostgresBackup.class);
 
 	final boolean wasCreated;
 	private final String url;
@@ -42,7 +40,6 @@
 		throws ClassNotFoundException, SQLException, LuanException
 	{
 		spec = new LuanTable(spec);
-		this.luanLogger = luan.getLogger(PostgresBackup.class);
 /*
 		Class.forName("org.postgresql.Driver");
 		url = "jdbc:postgresql://localhost:5432/luan";
@@ -120,7 +117,7 @@
 		updateStmt.setLong(2,id);
 		int n = updateStmt.executeUpdate();
 		if( n==0 ) {
-			luanLogger.error("update not found for id="+id+", trying add");
+			logger.error("update not found for id="+id+", trying add");
 			add(doc);
 		} else if( n!=1 )
 			throw new RuntimeException();