1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.http.log;
19
20 import com.google.common.base.Charsets;
21
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.io.PrintWriter;
26 import java.net.URL;
27 import java.net.URLConnection;
28 import java.util.regex.Pattern;
29
30 import javax.net.ssl.HttpsURLConnection;
31 import javax.net.ssl.SSLSocketFactory;
32 import javax.servlet.ServletException;
33 import javax.servlet.http.HttpServlet;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.commons.logging.impl.Jdk14Logger;
40 import org.apache.commons.logging.impl.Log4JLogger;
41 import org.apache.hadoop.HadoopIllegalArgumentException;
42 import org.apache.hadoop.conf.Configuration;
43 import org.apache.hadoop.conf.Configured;
44 import org.apache.hadoop.hbase.classification.InterfaceAudience;
45 import org.apache.hadoop.hbase.classification.InterfaceStability;
46 import org.apache.hadoop.hbase.http.HttpServer;
47 import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
48 import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
49 import org.apache.hadoop.security.ssl.SSLFactory;
50 import org.apache.hadoop.util.ServletUtil;
51 import org.apache.hadoop.util.Tool;
52
53
54
55
56 @InterfaceStability.Evolving
57 public class LogLevel {
58 private static final String USAGES = "\nUsage: General options are:\n"
59 + "\t[-getlevel <host:port> <classname> [-protocol (http|https)]\n"
60 + "\t[-setlevel <host:port> <classname> <level> [-protocol (http|https)]";
61
62 public static final String PROTOCOL_HTTP = "http";
63 public static final String PROTOCOL_HTTPS = "https";
64
65
66
67
68 public static void main(String[] args) throws Exception {
69 CLI cli = new CLI(new Configuration());
70 System.exit(cli.run(args));
71 }
72
73
74
75
76 private enum Operations {
77 GETLEVEL,
78 SETLEVEL,
79 UNKNOWN
80 }
81
82 private static void printUsage() {
83 System.err.println(USAGES);
84 System.exit(-1);
85 }
86
87 public static boolean isValidProtocol(String protocol) {
88 return ((protocol.equals(PROTOCOL_HTTP) || protocol.equals(PROTOCOL_HTTPS)));
89 }
90
91 @InterfaceAudience.Private
92 static class CLI extends Configured implements Tool {
93 private Operations operation = Operations.UNKNOWN;
94 private String protocol;
95 private String hostName;
96 private String className;
97 private String level;
98
99 CLI(Configuration conf) {
100 setConf(conf);
101 }
102
103 @Override
104 public int run(String[] args) throws Exception {
105 try {
106 parseArguments(args);
107 sendLogLevelRequest();
108 } catch (HadoopIllegalArgumentException e) {
109 printUsage();
110 }
111 return 0;
112 }
113
114
115
116
117
118
119 private void sendLogLevelRequest()
120 throws HadoopIllegalArgumentException, Exception {
121 switch (operation) {
122 case GETLEVEL:
123 doGetLevel();
124 break;
125 case SETLEVEL:
126 doSetLevel();
127 break;
128 default:
129 throw new HadoopIllegalArgumentException(
130 "Expect either -getlevel or -setlevel");
131 }
132 }
133
134 public void parseArguments(String[] args) throws
135 HadoopIllegalArgumentException {
136 if (args.length == 0) {
137 throw new HadoopIllegalArgumentException("No arguments specified");
138 }
139 int nextArgIndex = 0;
140 while (nextArgIndex < args.length) {
141 switch (args[nextArgIndex]) {
142 case "-getlevel":
143 nextArgIndex = parseGetLevelArgs(args, nextArgIndex);
144 break;
145 case "-setlevel":
146 nextArgIndex = parseSetLevelArgs(args, nextArgIndex);
147 break;
148 case "-protocol":
149 nextArgIndex = parseProtocolArgs(args, nextArgIndex);
150 break;
151 default:
152 throw new HadoopIllegalArgumentException(
153 "Unexpected argument " + args[nextArgIndex]);
154 }
155 }
156
157
158 if (operation == Operations.UNKNOWN) {
159 throw new HadoopIllegalArgumentException(
160 "Must specify either -getlevel or -setlevel");
161 }
162
163
164 if (protocol == null) {
165 protocol = PROTOCOL_HTTP;
166 }
167 }
168
169 private int parseGetLevelArgs(String[] args, int index) throws
170 HadoopIllegalArgumentException {
171
172 if (operation != Operations.UNKNOWN) {
173 throw new HadoopIllegalArgumentException("Redundant -getlevel command");
174 }
175
176 if (index + 2 >= args.length) {
177 throw new HadoopIllegalArgumentException("-getlevel needs two parameters");
178 }
179 operation = Operations.GETLEVEL;
180 hostName = args[index + 1];
181 className = args[index + 2];
182 return index + 3;
183 }
184
185 private int parseSetLevelArgs(String[] args, int index) throws
186 HadoopIllegalArgumentException {
187
188 if (operation != Operations.UNKNOWN) {
189 throw new HadoopIllegalArgumentException("Redundant -setlevel command");
190 }
191
192 if (index + 3 >= args.length) {
193 throw new HadoopIllegalArgumentException("-setlevel needs three parameters");
194 }
195 operation = Operations.SETLEVEL;
196 hostName = args[index + 1];
197 className = args[index + 2];
198 level = args[index + 3];
199 return index + 4;
200 }
201
202 private int parseProtocolArgs(String[] args, int index) throws
203 HadoopIllegalArgumentException {
204
205 if (protocol != null) {
206 throw new HadoopIllegalArgumentException("Redundant -protocol command");
207 }
208
209 if (index + 1 >= args.length) {
210 throw new HadoopIllegalArgumentException("-protocol needs one parameter");
211 }
212
213 protocol = args[index + 1];
214 if (!isValidProtocol(protocol)) {
215 throw new HadoopIllegalArgumentException("Invalid protocol: " + protocol);
216 }
217 return index + 2;
218 }
219
220
221
222
223
224
225
226 private void doGetLevel() throws Exception {
227 process(protocol + "://" + hostName + "/logLevel?log=" + className);
228 }
229
230
231
232
233
234
235
236 private void doSetLevel() throws Exception {
237 process(protocol + "://" + hostName + "/logLevel?log=" + className
238 + "&level=" + level);
239 }
240
241
242
243
244
245
246
247
248
249
250 private URLConnection connect(URL url) throws Exception {
251 AuthenticatedURL.Token token = new AuthenticatedURL.Token();
252 AuthenticatedURL aUrl;
253 SSLFactory clientSslFactory;
254 URLConnection connection;
255
256
257 if (PROTOCOL_HTTPS.equals(url.getProtocol())) {
258 clientSslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, this.getConf());
259 clientSslFactory.init();
260 SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory();
261
262 aUrl = new AuthenticatedURL(new KerberosAuthenticator(), clientSslFactory);
263 connection = aUrl.openConnection(url, token);
264 HttpsURLConnection httpsConn = (HttpsURLConnection) connection;
265 httpsConn.setSSLSocketFactory(sslSocketF);
266 } else {
267 aUrl = new AuthenticatedURL(new KerberosAuthenticator());
268 connection = aUrl.openConnection(url, token);
269 }
270 connection.connect();
271 return connection;
272 }
273
274
275
276
277
278
279
280 private void process(String urlString) throws Exception {
281 URL url = new URL(urlString);
282 System.out.println("Connecting to " + url);
283
284 URLConnection connection = connect(url);
285
286
287
288 try (InputStreamReader streamReader =
289 new InputStreamReader(connection.getInputStream(), Charsets.UTF_8);
290 BufferedReader bufferedReader = new BufferedReader(streamReader)) {
291 String line;
292 while((line = bufferedReader.readLine()) != null) {
293 if (line.startsWith(MARKER)) {
294 System.out.println(TAG.matcher(line).replaceAll(""));
295 }
296 }
297 } catch (IOException ioe) {
298 System.err.println("" + ioe);
299 }
300 }
301 }
302
303 private static final String MARKER = "<!-- OUTPUT -->";
304 private static final Pattern TAG = Pattern.compile("<[^>]*>");
305
306
307
308
309 @InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
310 @InterfaceStability.Unstable
311 public static class Servlet extends HttpServlet {
312 private static final long serialVersionUID = 1L;
313
314 @Override
315 public void doGet(HttpServletRequest request, HttpServletResponse response)
316 throws ServletException, IOException {
317
318
319 if (!HttpServer.hasAdministratorAccess(getServletContext(), request,
320 response)) {
321 return;
322 }
323
324 PrintWriter out = ServletUtil.initHTML(response, "Log Level");
325 String logName = ServletUtil.getParameter(request, "log");
326 String level = ServletUtil.getParameter(request, "level");
327
328 if (logName != null) {
329 out.println("<br /><hr /><h3>Results</h3>");
330 out.println(MARKER
331 + "Submitted Log Name: <b>" + logName + "</b><br />");
332
333 Log log = LogFactory.getLog(logName);
334 out.println(MARKER
335 + "Log Class: <b>" + log.getClass().getName() +"</b><br />");
336 if (level != null) {
337 out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />");
338 }
339
340 if (log instanceof Log4JLogger) {
341 process(((Log4JLogger)log).getLogger(), level, out);
342 }
343 else if (log instanceof Jdk14Logger) {
344 process(((Jdk14Logger)log).getLogger(), level, out);
345 }
346 else {
347 out.println("Sorry, " + log.getClass() + " not supported.<br />");
348 }
349 }
350
351 out.println(FORMS);
352 out.println(ServletUtil.HTML_TAIL);
353 }
354
355 static final String FORMS = "\n<br /><hr /><h3>Get / Set</h3>"
356 + "\n<form>Log: <input type='text' size='50' name='log' /> "
357 + "<input type='submit' value='Get Log Level' />"
358 + "</form>"
359 + "\n<form>Log: <input type='text' size='50' name='log' /> "
360 + "Level: <input type='text' name='level' /> "
361 + "<input type='submit' value='Set Log Level' />"
362 + "</form>";
363
364 private static void process(org.apache.log4j.Logger log, String level, PrintWriter out) {
365 if (level != null) {
366 if (!level.equals(org.apache.log4j.Level.toLevel(level).toString())) {
367 out.println(MARKER + "Bad level : <b>" + level + "</b><br />");
368 } else {
369 log.setLevel(org.apache.log4j.Level.toLevel(level));
370 out.println(MARKER + "Setting Level to " + level + " ...<br />");
371 }
372 }
373 out.println(MARKER
374 + "Effective level: <b>" + log.getEffectiveLevel() + "</b><br />");
375 }
376
377 private static void process(java.util.logging.Logger log, String level,
378 PrintWriter out) {
379 if (level != null) {
380 log.setLevel(java.util.logging.Level.parse(level));
381 out.println(MARKER + "Setting Level to " + level + " ...<br />");
382 }
383
384 java.util.logging.Level lev;
385 while ((lev = log.getLevel()) == null) {
386 log = log.getParent();
387 }
388 out.println(MARKER + "Effective level: <b>" + lev + "</b><br />");
389 }
390 }
391 }