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.log;
019
020import java.io.*;
021import java.net.*;
022import java.util.regex.Pattern;
023
024import javax.servlet.*;
025import javax.servlet.http.*;
026
027import com.google.common.base.Charsets;
028import org.apache.commons.logging.*;
029import org.apache.commons.logging.impl.*;
030import org.apache.hadoop.classification.InterfaceAudience;
031import org.apache.hadoop.classification.InterfaceStability;
032import org.apache.hadoop.conf.Configuration;
033import org.apache.hadoop.http.HttpServer2;
034import org.apache.hadoop.security.UserGroupInformation;
035import org.apache.hadoop.util.ServletUtil;
036
037/**
038 * Change log level in runtime.
039 */
040@InterfaceStability.Evolving
041public class LogLevel {
042  public static final String USAGES = "\nUsage: General options are:\n"
043      + "\t[-getlevel <host:httpPort> <name>]\n"
044      + "\t[-setlevel <host:httpPort> <name> <level>]\n";
045
046  /**
047   * A command line implementation
048   */
049  public static void main(String[] args) {
050    String httpScheme = UserGroupInformation.isSecurityEnabled()
051      ? "https://"
052      : "http://";
053
054    if (args.length == 3 && "-getlevel".equals(args[0])) {
055      process(httpScheme + args[1] + "/logLevel?log=" + args[2]);
056      return;
057    }
058    else if (args.length == 4 && "-setlevel".equals(args[0])) {
059      process(httpScheme + args[1] + "/logLevel?log=" + args[2]
060              + "&level=" + args[3]);
061      return;
062    }
063
064    System.err.println(USAGES);
065    System.exit(-1);
066  }
067
068  private static void process(String urlstring) {
069    try {
070      URL url = new URL(urlstring);
071      System.out.println("Connecting to " + url);
072
073      URLConnection connection = UserGroupInformation.isSecurityEnabled()
074        ? SecureHTTPURLConnectionProvider.openConnection(url)
075        : url.openConnection();
076
077      connection.connect();
078
079      BufferedReader in = new BufferedReader(new InputStreamReader(
080          connection.getInputStream(), Charsets.UTF_8));
081      for(String line; (line = in.readLine()) != null; )
082        if (line.startsWith(MARKER)) {
083          System.out.println(TAG.matcher(line).replaceAll(""));
084        }
085      in.close();
086    } catch (IOException ioe) {
087      System.err.println("" + ioe);
088    }
089  }
090
091  static final String MARKER = "<!-- OUTPUT -->";
092  static final Pattern TAG = Pattern.compile("<[^>]*>");
093
094  /**
095   * A servlet implementation
096   */
097  @InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
098  @InterfaceStability.Unstable
099  public static class Servlet extends HttpServlet {
100    private static final long serialVersionUID = 1L;
101
102    @Override
103    public void doGet(HttpServletRequest request, HttpServletResponse response
104        ) throws ServletException, IOException {
105
106      // Do the authorization
107      if (!HttpServer2.hasAdministratorAccess(getServletContext(), request,
108          response)) {
109        return;
110      }
111
112      PrintWriter out = ServletUtil.initHTML(response, "Log Level");
113      String logName = ServletUtil.getParameter(request, "log");
114      String level = ServletUtil.getParameter(request, "level");
115
116      if (logName != null) {
117        out.println("<br /><hr /><h3>Results</h3>");
118        out.println(MARKER
119            + "Submitted Log Name: <b>" + logName + "</b><br />");
120
121        Log log = LogFactory.getLog(logName);
122        out.println(MARKER
123            + "Log Class: <b>" + log.getClass().getName() +"</b><br />");
124        if (level != null) {
125          out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />");
126        }
127
128        if (log instanceof Log4JLogger) {
129          process(((Log4JLogger)log).getLogger(), level, out);
130        }
131        else if (log instanceof Jdk14Logger) {
132          process(((Jdk14Logger)log).getLogger(), level, out);
133        }
134        else {
135          out.println("Sorry, " + log.getClass() + " not supported.<br />");
136        }
137      }
138
139      out.println(FORMS);
140      out.println(ServletUtil.HTML_TAIL);
141    }
142
143    static final String FORMS = "\n<br /><hr /><h3>Get / Set</h3>"
144        + "\n<form>Log: <input type='text' size='50' name='log' /> "
145        + "<input type='submit' value='Get Log Level' />"
146        + "</form>"
147        + "\n<form>Log: <input type='text' size='50' name='log' /> "
148        + "Level: <input type='text' name='level' /> "
149        + "<input type='submit' value='Set Log Level' />"
150        + "</form>";
151
152    private static void process(org.apache.log4j.Logger log, String level,
153        PrintWriter out) throws IOException {
154      if (level != null) {
155        if (!level.equals(org.apache.log4j.Level.toLevel(level).toString())) {
156          out.println(MARKER + "Bad level : <b>" + level + "</b><br />");
157        } else {
158          log.setLevel(org.apache.log4j.Level.toLevel(level));
159          out.println(MARKER + "Setting Level to " + level + " ...<br />");
160        }
161      }
162      out.println(MARKER
163          + "Effective level: <b>" + log.getEffectiveLevel() + "</b><br />");
164    }
165
166    private static void process(java.util.logging.Logger log, String level,
167        PrintWriter out) throws IOException {
168      if (level != null) {
169        log.setLevel(java.util.logging.Level.parse(level));
170        out.println(MARKER + "Setting Level to " + level + " ...<br />");
171      }
172
173      java.util.logging.Level lev;
174      for(; (lev = log.getLevel()) == null; log = log.getParent());
175      out.println(MARKER + "Effective level: <b>" + lev + "</b><br />");
176    }
177  }
178}