SOLR-554 -- Hierarchical JDK log level selector for SOLR Admin replaces logging.jsp

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@682264 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Shalin Shekhar Mangar 2008-08-04 06:03:46 +00:00
parent b8c2b71e61
commit d222a0da07
4 changed files with 302 additions and 2 deletions

View File

@ -339,7 +339,9 @@ New Features
67. SOLR-622: SpellCheckComponent supports auto-loading indices on startup and optionally, (re)builds indices 67. SOLR-622: SpellCheckComponent supports auto-loading indices on startup and optionally, (re)builds indices
on newSearcher event, if configured in solrconfig.xml on newSearcher event, if configured in solrconfig.xml
(shalin) (shalin)
68. SOLR-554: Hierarchical JDK log level selector for SOLR Admin replaces logging.jsp (Sean Timm via shalin)
Changes in runtime behavior Changes in runtime behavior
1. SOLR-559: use Lucene updateDocument, deleteDocuments methods. This 1. SOLR-559: use Lucene updateDocument, deleteDocuments methods. This

View File

@ -0,0 +1,288 @@
/**
* 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.solr.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
/**
* Admin JDK Logger level report and selection servlet.
*
* @version $Id$
* @since solr 1.3
*/
public final class LogLevelSelection extends HttpServlet {
public void init() throws ServletException {
}
/**
* Processes an HTTP GET request and changes the logging level as
* specified.
*/
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// Output page
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.write("<html><head>\n");
out.write("<title>Solr Admin: JDK Log Level Selector</title>\n");
out.write("<link rel=\"stylesheet\" type=\"text/css\" href=\"solr-admin.css\" />");
out.write("</head><body>\n");
out.write("<a href=\".\"><img border=\"0\" align=\"right\" height=\"61\" width=\"142\" src=\"solr-head.gif\" alt=\"Solr\"></a>");
out.write("<h1>JDK Log Level Selector</h1>");
out.write("<p>Below is the complete JDK Log hierarchy with " +
"intermediate logger/categories synthesized. " +
"The effective logging level is shown to the " +
"far right. If a logger has unset level, then " +
"the effective level is that of the nearest ancestor " +
"with a level setting. Note that this only shows " +
"JDK Log levels.</p>\n");
out.write("<form action='");
out.write(request.getRequestURI());
out.write("' method='POST'>\n");
out.write("<input type='submit' name='submit' value='set' " +
"class='button'>\n");
out.write("<input type='submit' name='submit' value='cancel' " +
"class='button'>\n");
out.write("<br><br>\n");
out.write("<table cellspacing='2' cellpadding='2'>");
out.write("<tr bgcolor='#CCCCFF'>" +
"<th align=left>Logger/Category name<br>" +
"<th colspan=9>Level</th>" +
"</tr><tr bgcolor='#CCCCFF'>" +
"<td bgcolor='#AAAAAA'>" +
"(Dark rows don't yet exist.)</td>");
for (int j = 0; j < LEVELS.length; ++j) {
out.write("<th align=left>");
if (LEVELS[j] != null) out.write(LEVELS[j].toString());
else out.write("unset");
out.write("</th>");
}
out.write("<th align=left>Effective</th>\n");
out.write("</tr>\n");
Iterator iWrappers = buildWrappers().iterator();
while (iWrappers.hasNext()) {
LogWrapper wrapper = (LogWrapper) iWrappers.next();
out.write("<tr");
if (wrapper.logger == null) {
out.write(" bgcolor='#AAAAAA'");
}
//out.write( ( wrapper.logger != null ) ? "#DDDDDD" : "#AAAAAA" );
out.write("><td>");
if ("".equals(wrapper.name)) {
out.write("root");
} else {
out.write(wrapper.name);
}
out.write("</td>\n");
for (int j = 0; j < LEVELS.length; ++j) {
out.write("<td align=center>");
if (!wrapper.name.equals("root") ||
(LEVELS[j] != null)) {
out.write("<input type='radio' name='");
if ("".equals(wrapper.name)) {
out.write("root");
} else {
out.write(wrapper.name);
}
out.write("' value='");
if (LEVELS[j] != null) out.write(LEVELS[j].toString());
else out.write("unset");
out.write('\'');
if (LEVELS[j] == wrapper.level()) out.write(" checked");
out.write('>');
}
out.write("</td>\n");
}
out.write("<td align=center>");
if (wrapper.logger != null) {
out.write(getEffectiveLevel(wrapper.logger).toString());
}
out.write("</td></tr>\n");
}
out.write("</table>\n");
out.write("<br>\n");
out.write("<input type='submit' name='submit' value='set' " +
"class='button'>\n");
out.write("<input type='submit' name='submit' value='cancel' " +
"class='button'>\n");
out.write("</form>\n");
out.write("</body></html>\n");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
if (request.getParameter("submit").equals("set")) {
Map paramMap = request.getParameterMap();
Iterator iParams = paramMap.entrySet().iterator();
while (iParams.hasNext()) {
Map.Entry p = (Map.Entry) iParams.next();
String name = (String) p.getKey();
String value = ((String[]) p.getValue())[0];
if (name.equals("submit")) continue;
Logger logger;
LogManager logManager = LogManager.getLogManager();
if ("root".equals(name)) {
logger = logManager.getLogger("");
} else logger = logManager.getLogger(name);
if ("unset".equals(value)) {
if ((logger != null) && (logger.getLevel() != null)) {
logger.setLevel(null);
log.info("Unset log level on '" + name + "'.");
}
} else {
Level level = Level.parse(value);
if (logger == null) logger = Logger.getLogger(name);
if (logger.getLevel() != level) {
logger.setLevel(level);
log.info("Set '" + name + "' to " +
level + " level.");
}
}
}
} else {
log.fine("Selection form cancelled");
}
// Redirect back to standard get page.
response.sendRedirect(request.getRequestURI());
}
private Collection buildWrappers() {
// Use tree to get sorted results
SortedSet<LogWrapper> roots = new TreeSet<LogWrapper>();
roots.add(LogWrapper.ROOT);
LogManager logManager = LogManager.getLogManager();
Enumeration<String> loggerNames = logManager.getLoggerNames();
while (loggerNames.hasMoreElements()) {
String name = loggerNames.nextElement();
Logger logger = Logger.getLogger(name);
LogWrapper wrapper = new LogWrapper(logger);
roots.remove(wrapper); // Make sure add occurs
roots.add(wrapper);
while (true) {
int dot = name.lastIndexOf(".");
if (dot < 0) break;
name = name.substring(0, dot);
roots.add(new LogWrapper(name)); // if not already
}
}
return roots;
}
private Level getEffectiveLevel(Logger logger) {
Level level = logger.getLevel();
if (level != null) {
return level;
}
for (Level l : LEVELS) {
if (l == null) {
continue;
}
if (logger.isLoggable(l)) {
level = l;
}
}
return level;
}
private static class LogWrapper
implements Comparable {
public static LogWrapper ROOT =
new LogWrapper(LogManager.getLogManager().getLogger(""));
public LogWrapper(Logger logger) {
this.logger = logger;
this.name = logger.getName();
}
public LogWrapper(String name) {
this.name = name;
}
public int compareTo(Object other) {
if (this.equals(other)) return 0;
if (this == ROOT) return -1;
if (other == ROOT) return 1;
return name.compareTo(((LogWrapper) other).name);
}
public boolean equals(Object other) {
return name.equals(((LogWrapper) other).name);
}
public Level level() {
if (logger != null) return logger.getLevel();
return null;
}
public Logger logger = null;
public String name;
}
private static Level[] LEVELS = {
null, // aka unset
Level.FINEST,
Level.FINE,
Level.CONFIG,
Level.INFO,
Level.WARNING,
Level.SEVERE,
Level.OFF
// Level.ALL -- ignore. It is useless.
};
private Logger log = Logger.getLogger(getClass().getName());
}

View File

@ -101,6 +101,11 @@
<load-on-startup>2</load-on-startup> <load-on-startup>2</load-on-startup>
</servlet> </servlet>
<servlet>
<servlet-name>Logging</servlet-name>
<servlet-class>org.apache.solr.servlet.LogLevelSelection</servlet-class>
</servlet>
<!-- @Deprecated --> <!-- @Deprecated -->
<servlet> <servlet>
<servlet-name>ping</servlet-name> <servlet-name>ping</servlet-name>
@ -117,6 +122,11 @@
<url-pattern>/update/*</url-pattern> <url-pattern>/update/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>Logging</servlet-name>
<url-pattern>/admin/logging</url-pattern>
</servlet-mapping>
<!-- @Deprecated --> <!-- @Deprecated -->
<servlet-mapping> <servlet-mapping>
<servlet-name>ping</servlet-name> <servlet-name>ping</servlet-name>

View File

@ -43,7 +43,7 @@
[<a href="registry.jsp">Info</a>] [<a href="registry.jsp">Info</a>]
[<a href="distributiondump.jsp">Distribution</a>] [<a href="distributiondump.jsp">Distribution</a>]
[<a href="ping">Ping</a>] [<a href="ping">Ping</a>]
[<a href="logging.jsp">Logging</a>] [<a href="logging">Logging</a>]
</td> </td>
</tr> </tr>