001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.http.log; 019 020import java.io.BufferedReader; 021import java.io.FileNotFoundException; 022import java.io.IOException; 023import java.io.InputStreamReader; 024import java.io.PrintWriter; 025import java.net.URL; 026import java.net.URLConnection; 027import java.util.regex.Pattern; 028import javax.servlet.ServletException; 029import javax.servlet.http.HttpServlet; 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032import org.apache.commons.logging.impl.Jdk14Logger; 033import org.apache.commons.logging.impl.Log4JLogger; 034import org.apache.hadoop.hbase.http.HttpServer; 035import org.apache.hadoop.util.ServletUtil; 036import org.apache.log4j.LogManager; 037import org.apache.yetus.audience.InterfaceAudience; 038import org.apache.yetus.audience.InterfaceStability; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041import org.slf4j.impl.Log4jLoggerAdapter; 042 043/** 044 * Change log level in runtime. 045 */ 046@InterfaceAudience.Private 047public final class LogLevel { 048 public static final String USAGES = "\nUsage: General options are:\n" 049 + "\t[-getlevel <host:httpPort> <name>]\n" 050 + "\t[-setlevel <host:httpPort> <name> <level>]\n"; 051 052 /** 053 * A command line implementation 054 */ 055 public static void main(String[] args) { 056 if (args.length == 3 && "-getlevel".equals(args[0])) { 057 process("http://" + args[1] + "/logLevel?log=" + args[2]); 058 return; 059 } 060 else if (args.length == 4 && "-setlevel".equals(args[0])) { 061 process("http://" + args[1] + "/logLevel?log=" + args[2] 062 + "&level=" + args[3]); 063 return; 064 } 065 066 System.err.println(USAGES); 067 System.exit(-1); 068 } 069 070 private static void process(String urlstring) { 071 try { 072 URL url = new URL(urlstring); 073 System.out.println("Connecting to " + url); 074 URLConnection connection = url.openConnection(); 075 connection.connect(); 076 try (InputStreamReader streamReader = new InputStreamReader(connection.getInputStream()); 077 BufferedReader bufferedReader = new BufferedReader(streamReader)) { 078 for(String line; (line = bufferedReader.readLine()) != null; ) { 079 if (line.startsWith(MARKER)) { 080 System.out.println(TAG.matcher(line).replaceAll("")); 081 } 082 } 083 } 084 } catch (IOException ioe) { 085 System.err.println("" + ioe); 086 } 087 } 088 089 static final String MARKER = "<!-- OUTPUT -->"; 090 static final Pattern TAG = Pattern.compile("<[^>]*>"); 091 092 /** 093 * A servlet implementation 094 */ 095 @InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"}) 096 @InterfaceStability.Unstable 097 public static class Servlet extends HttpServlet { 098 private static final long serialVersionUID = 1L; 099 100 @Override 101 public void doGet(HttpServletRequest request, HttpServletResponse response 102 ) throws ServletException, IOException { 103 104 // Do the authorization 105 if (!HttpServer.hasAdministratorAccess(getServletContext(), request, 106 response)) { 107 return; 108 } 109 response.setContentType("text/html"); 110 PrintWriter out; 111 try { 112 String headerPath = "header.jsp?pageTitle=Log Level"; 113 request.getRequestDispatcher(headerPath).include(request, response); 114 out = response.getWriter(); 115 } catch (FileNotFoundException e) { 116 // in case file is not found fall back to old design 117 out = ServletUtil.initHTML(response, "Log Level"); 118 } 119 out.println(FORMS); 120 121 String logName = ServletUtil.getParameter(request, "log"); 122 String level = ServletUtil.getParameter(request, "level"); 123 124 if (logName != null) { 125 out.println("<p>Results:</p>"); 126 out.println(MARKER 127 + "Submitted Log Name: <b>" + logName + "</b><br />"); 128 129 Logger log = LoggerFactory.getLogger(logName); 130 out.println(MARKER 131 + "Log Class: <b>" + log.getClass().getName() +"</b><br />"); 132 if (level != null) { 133 out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />"); 134 } 135 136 if (log instanceof Log4JLogger) { 137 process(((Log4JLogger)log).getLogger(), level, out); 138 } else if (log instanceof Jdk14Logger) { 139 process(((Jdk14Logger)log).getLogger(), level, out); 140 } else if (log instanceof Log4jLoggerAdapter) { 141 process(LogManager.getLogger(logName), level, out); 142 } else { 143 out.println("Sorry, " + log.getClass() + " not supported.<br />"); 144 } 145 } 146 147 try { 148 String footerPath = "footer.jsp"; 149 out.println("</div>"); 150 request.getRequestDispatcher(footerPath).include(request, response); 151 } catch (FileNotFoundException e) { 152 out.println(ServletUtil.HTML_TAIL); 153 } 154 out.close(); 155 } 156 157 static final String FORMS = "<div class='container-fluid content'>\n" 158 + "<div class='row inner_header'>\n" + "<div class='page-header'>\n" 159 + "<h1>Get/Set Log Level</h1>\n" + "</div>\n" + "</div>\n" + "Actions:" + "<p>" 160 + "<center>\n" + "<table class='table' style='border: 0;' width='95%' >\n" + "<tr>\n" 161 + "<form>\n" + "<td class='centered'>\n" 162 + "<input style='font-size: 12pt; width: 10em' type='submit' value='Get Log Level'" 163 + " class='btn' />\n" + "</td>\n" + "<td style='text-align: center;'>\n" 164 + "<input type='text' name='log' size='50' required='required'" 165 + " placeholder='Log Name (required)' />\n" + "</td>\n" + "<td width=\"40%\">" 166 + "Get the current log level for the specified log name." + "</td>\n" + "</form>\n" 167 + "</tr>\n" + "<tr>\n" + "<form>\n" + "<td class='centered'>\n" 168 + "<input style='font-size: 12pt; width: 10em' type='submit'" 169 + " value='Set Log Level' class='btn' />\n" + "</td>\n" 170 + "<td style='text-align: center;'>\n" 171 + "<input type='text' name='log' size='50' required='required'" 172 + " placeholder='Log Name (required)' />\n" 173 + "<input type='text' name='level' size='50' required='required'" 174 + " placeholder='Log Level (required)' />\n" + "</td>\n" + "<td width=\"40%\" style=\"\">" 175 + "Set the specified log level for the specified log name." + "</td>\n" + "</form>\n" 176 + "</tr>\n" + "</table>\n" + "</center>\n" + "</p>\n" + "<hr/>\n"; 177 178 private static void process(org.apache.log4j.Logger log, String level, 179 PrintWriter out) throws IOException { 180 if (level != null) { 181 if (!level.equals(org.apache.log4j.Level.toLevel(level).toString())) { 182 out.println(MARKER + "<div class='text-danger'>" + "Bad level : <strong>" + level 183 + "</strong><br />" + "</div>"); 184 } else { 185 log.setLevel(org.apache.log4j.Level.toLevel(level)); 186 out.println(MARKER + "<div class='text-success'>" + "Setting Level to <strong>" + level 187 + "</strong> ...<br />" + "</div>"); 188 } 189 } 190 out.println(MARKER 191 + "Effective level: <b>" + log.getEffectiveLevel() + "</b><br />"); 192 } 193 194 private static void process(java.util.logging.Logger log, String level, 195 PrintWriter out) throws IOException { 196 if (level != null) { 197 log.setLevel(java.util.logging.Level.parse(level)); 198 out.println(MARKER + "Setting Level to " + level + " ...<br />"); 199 } 200 201 java.util.logging.Level lev; 202 for(; (lev = log.getLevel()) == null; log = log.getParent()); 203 out.println(MARKER + "Effective level: <b>" + lev + "</b><br />"); 204 } 205 } 206 207 private LogLevel() {} 208}