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.IOException; 022import java.io.InputStreamReader; 023import java.io.PrintWriter; 024import java.net.URL; 025import java.net.URLConnection; 026import java.util.regex.Pattern; 027import javax.servlet.ServletException; 028import javax.servlet.http.HttpServlet; 029import javax.servlet.http.HttpServletRequest; 030import javax.servlet.http.HttpServletResponse; 031import org.apache.commons.logging.impl.Jdk14Logger; 032import org.apache.commons.logging.impl.Log4JLogger; 033import org.apache.hadoop.hbase.http.HttpServer; 034import org.apache.hadoop.conf.Configuration; 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 // Disallow modification of the LogLevel if explicitly set to readonly 110 Configuration conf = (Configuration) getServletContext().getAttribute( 111 HttpServer.CONF_CONTEXT_ATTRIBUTE); 112 if (conf.getBoolean("hbase.master.ui.readonly", false)) { 113 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Modification of HBase via" 114 + " the UI is disallowed in configuration."); 115 return; 116 } 117 118 PrintWriter out = ServletUtil.initHTML(response, "Log Level"); 119 String logName = ServletUtil.getParameter(request, "log"); 120 String level = ServletUtil.getParameter(request, "level"); 121 122 if (logName != null) { 123 out.println("<br /><hr /><h3>Results</h3>"); 124 out.println(MARKER 125 + "Submitted Log Name: <b>" + logName + "</b><br />"); 126 127 Logger log = LoggerFactory.getLogger(logName); 128 out.println(MARKER 129 + "Log Class: <b>" + log.getClass().getName() +"</b><br />"); 130 if (level != null) { 131 out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />"); 132 } 133 134 if (log instanceof Log4JLogger) { 135 process(((Log4JLogger)log).getLogger(), level, out); 136 } else if (log instanceof Jdk14Logger) { 137 process(((Jdk14Logger)log).getLogger(), level, out); 138 } else if (log instanceof Log4jLoggerAdapter) { 139 process(LogManager.getLogger(logName), level, out); 140 } else { 141 out.println("Sorry, " + log.getClass() + " not supported.<br />"); 142 } 143 } 144 145 out.println(FORMS); 146 out.println(ServletUtil.HTML_TAIL); 147 } 148 149 static final String FORMS = "\n<br /><hr /><h3>Get / Set</h3>" 150 + "\n<form>Log: <input type='text' size='50' name='log' /> " 151 + "<input type='submit' value='Get Log Level' />" 152 + "</form>" 153 + "\n<form>Log: <input type='text' size='50' name='log' /> " 154 + "Level: <input type='text' name='level' /> " 155 + "<input type='submit' value='Set Log Level' />" 156 + "</form>"; 157 158 private static void process(org.apache.log4j.Logger log, String level, 159 PrintWriter out) throws IOException { 160 if (level != null) { 161 if (!level.equals(org.apache.log4j.Level.toLevel(level).toString())) { 162 out.println(MARKER + "Bad level : <b>" + level + "</b><br />"); 163 } else { 164 log.setLevel(org.apache.log4j.Level.toLevel(level)); 165 out.println(MARKER + "Setting Level to " + level + " ...<br />"); 166 } 167 } 168 out.println(MARKER 169 + "Effective level: <b>" + log.getEffectiveLevel() + "</b><br />"); 170 } 171 172 private static void process(java.util.logging.Logger log, String level, 173 PrintWriter out) throws IOException { 174 if (level != null) { 175 log.setLevel(java.util.logging.Level.parse(level)); 176 out.println(MARKER + "Setting Level to " + level + " ...<br />"); 177 } 178 179 java.util.logging.Level lev; 180 for(; (lev = log.getLevel()) == null; log = log.getParent()); 181 out.println(MARKER + "Effective level: <b>" + lev + "</b><br />"); 182 } 183 } 184 185 private LogLevel() {} 186}