SOLR-4778: Move LogWatcher init code out of CoreContainer

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1478152 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Alan Woodward 2013-05-01 19:25:52 +00:00
parent 46e43e1e8b
commit f35a93ef67
7 changed files with 217 additions and 112 deletions

View File

@ -51,6 +51,10 @@ Apache ZooKeeper 3.4.5
Upgrading from Solr 4.3.0
----------------------
* SOLR-4778: The signature of LogWatcher.registerListener has changed, from
(ListenerConfig, CoreContainer) to (ListenerConfig). Users implementing their
own LogWatcher classes will need to change their code accordingly.
Detailed Change List
----------------------
@ -99,6 +103,8 @@ Other Changes
* SOLR-4759: Velocity (/browse) template cosmetic cleanup.
(Mark Bennett, ehatcher)
* SOLR-4778: LogWatcher init code moved out of CoreContainer (Alan Woodward)
================== 4.3.0 ==================
Versions of Major Components

View File

@ -17,6 +17,38 @@
package org.apache.solr.core;
import org.apache.commons.io.IOUtils;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.handler.component.HttpShardHandlerFactory;
import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.logging.jul.JulWatcher;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.FileUtils;
import org.apache.solr.util.PropertiesUtil;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPathExpressionException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@ -44,42 +76,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPathExpressionException;
import org.apache.commons.io.IOUtils;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.handler.component.HttpShardHandlerFactory;
import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.logging.ListenerConfig;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.logging.jul.JulWatcher;
import org.apache.solr.logging.log4j.Log4jWatcher;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.FileUtils;
import org.apache.solr.util.PropertiesUtil;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
/**
*
@ -282,51 +278,7 @@ public class CoreContainer
solrCores.allocateLazyCores(cfg, loader);
// Initialize Logging
if (cfg.getBool(ConfigSolr.CfgProp.SOLR_LOGGING_ENABLED, true)) {
String slf4jImpl = null;
String fname = cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_CLASS, null);
try {
slf4jImpl = StaticLoggerBinder.getSingleton()
.getLoggerFactoryClassStr();
if (fname == null) {
if (slf4jImpl.indexOf("Log4j") > 0) {
fname = "Log4j";
} else if (slf4jImpl.indexOf("JDK") > 0) {
fname = "JUL";
}
}
} catch (Throwable ex) {
log.warn("Unable to read SLF4J version. LogWatcher will be disabled: " + ex);
}
// Now load the framework
if (fname != null) {
if ("JUL".equalsIgnoreCase(fname)) {
logging = new JulWatcher(slf4jImpl);
}
else if( "Log4j".equals(fname) ) {
logging = new Log4jWatcher(slf4jImpl);
} else {
try {
logging = loader.newInstance(fname, LogWatcher.class);
} catch (Throwable e) {
log.warn("Unable to load LogWatcher", e);
}
}
if (logging != null) {
ListenerConfig v = new ListenerConfig();
v.size = cfg.getInt(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, 50);
v.threshold = cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, null);
if (v.size > 0) {
log.info("Registering Log Listener");
logging.registerListener(v, this);
}
}
}
}
logging = JulWatcher.newRegisteredLogWatcher(cfg, loader);
if (cfg instanceof ConfigSolrXmlOld) { //TODO: Remove for 5.0
String dcoreName = cfg.get(ConfigSolr.CfgProp.SOLR_CORES_DEFAULT_CORE_NAME, null);

View File

@ -17,21 +17,29 @@
package org.apache.solr.logging;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.core.ConfigSolr;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.logging.jul.JulWatcher;
import org.apache.solr.logging.log4j.Log4jWatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.core.CoreContainer;
/**
* A Class to monitor Logging events and hold N events in memory
*
* This is abstract so we can support both JUL and Log4j (and other logging platforms)
*/
public abstract class LogWatcher<E> {
private static final Logger log = LoggerFactory.getLogger(LogWatcher.class);
protected CircularList<E> history;
protected long last = -1;
@ -98,10 +106,82 @@ public abstract class LogWatcher<E> {
public abstract long getTimestamp(E event);
public abstract SolrDocument toSolrDocument(E event);
public abstract void registerListener(ListenerConfig cfg, CoreContainer container);
public abstract void registerListener(ListenerConfig cfg);
public void reset() {
history.clear();
last = -1;
}
/**
* Create and register a LogWatcher.
*
* JUL and Log4j watchers are supported out-of-the-box. You can register your own
* LogWatcher implementation via the plugins architecture
*
* @param config the CoreContainer's config, with logging configuration details
* @param loader a SolrResourceLoader, to be used to load plugin LogWatcher implementations.
* Can be null if
*
* @return a LogWatcher configured for the container's logging framework
*/
public static LogWatcher newRegisteredLogWatcher(ConfigSolr config, SolrResourceLoader loader) {
if (!config.getBool(ConfigSolr.CfgProp.SOLR_LOGGING_ENABLED, true))
return null;
LogWatcher logWatcher = createWatcher(config, loader);
if (logWatcher != null) {
ListenerConfig v = new ListenerConfig();
v.size = config.getInt(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, 50);
v.threshold = config.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, null);
if (v.size > 0) {
log.info("Registering Log Listener");
logWatcher.registerListener(v);
}
}
return logWatcher;
}
private static LogWatcher createWatcher(ConfigSolr config, SolrResourceLoader loader) {
String fname = config.get(ConfigSolr.CfgProp.SOLR_LOGGING_CLASS, null);
String slf4jImpl;
try {
slf4jImpl = StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr();
if (fname == null) {
if (slf4jImpl.indexOf("Log4j") > 0) {
fname = "Log4j";
} else if (slf4jImpl.indexOf("JDK") > 0) {
fname = "JUL";
}
}
}
catch (Throwable e) {
log.warn("Unable to read SLF4J version. LogWatcher will be disabled: " + e);
return null;
}
if (fname == null) {
log.info("No LogWatcher configured");
return null;
}
if ("JUL".equalsIgnoreCase(fname))
return new JulWatcher(slf4jImpl);
if ("Log4j".equals(fname))
return new Log4jWatcher(slf4jImpl);
try {
return loader != null ? loader.newInstance(fname, LogWatcher.class) : null;
}
catch (Throwable e) {
log.warn("Unable to load LogWatcher {}: {}", fname, e);
}
return null;
}
}

View File

@ -16,6 +16,13 @@
*/
package org.apache.solr.logging.jul;
import com.google.common.base.Throwables;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.logging.CircularList;
import org.apache.solr.logging.ListenerConfig;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.logging.LoggerInfo;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@ -28,15 +35,6 @@ import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.logging.CircularList;
import org.apache.solr.logging.ListenerConfig;
import org.apache.solr.logging.LoggerInfo;
import org.apache.solr.logging.LogWatcher;
import com.google.common.base.Throwables;
public class JulWatcher extends LogWatcher<LogRecord> {
final String name;
@ -131,7 +129,7 @@ public class JulWatcher extends LogWatcher<LogRecord> {
}
@Override
public void registerListener(ListenerConfig cfg, CoreContainer container) {
public void registerListener(ListenerConfig cfg) {
if(history!=null) {
throw new IllegalStateException("History already registered");
}

View File

@ -17,6 +17,18 @@
package org.apache.solr.logging.log4j;
import com.google.common.base.Throwables;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.logging.CircularList;
import org.apache.solr.logging.ListenerConfig;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.logging.LoggerInfo;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@ -25,20 +37,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.logging.CircularList;
import org.apache.solr.logging.ListenerConfig;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.logging.LoggerInfo;
import com.google.common.base.Throwables;
public class Log4jWatcher extends LogWatcher<LoggingEvent> {
final String name;
@ -124,7 +122,7 @@ public class Log4jWatcher extends LogWatcher<LoggingEvent> {
}
@Override
public void registerListener(ListenerConfig cfg, CoreContainer container) {
public void registerListener(ListenerConfig cfg) {
if(history!=null) {
throw new IllegalStateException("History already registered");
}

View File

@ -0,0 +1,71 @@
package org.apache.solr.logging;
/*
* 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.
*/
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.core.ConfigSolr;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class TestLogWatcher {
private ConfigSolr config;
@Before
public void setUp() {
config = createMock(ConfigSolr.class);
expect(config.getBool(ConfigSolr.CfgProp.SOLR_LOGGING_ENABLED, true)).andReturn(true);
expect(config.getInt(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, 50)).andReturn(50);
expect(config.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, null)).andReturn(null);
expect(config.get(ConfigSolr.CfgProp.SOLR_LOGGING_CLASS, null)).andReturn(null);
replay(config);
}
@Test
public void testLog4jWatcher() {
Logger log = LoggerFactory.getLogger("testlogger");
LogWatcher watcher = LogWatcher.newRegisteredLogWatcher(config, null);
assertEquals(watcher.getLastEvent(), -1);
log.warn("This is a test message");
assertTrue(watcher.getLastEvent() > -1);
SolrDocumentList events = watcher.getHistory(-1, new AtomicBoolean());
assertEquals(events.size(), 1);
SolrDocument event = events.get(0);
assertEquals(event.get("logger"), "testlogger");
assertEquals(event.get("message"), "This is a test message");
}
}

View File

@ -201,7 +201,7 @@ public class TestHarness extends BaseTestHarness {
throw new RuntimeException(e);
}
LogWatcher<?> logging = new JulWatcher("test");
logging.registerListener(new ListenerConfig(), container);
logging.registerListener(new ListenerConfig());
container.setLogging(logging);
CoreDescriptor dcore = new CoreDescriptor(container, coreName, solrConfig.getResourceLoader().getInstanceDir());