You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by ak...@apache.org on 2017/08/23 20:56:21 UTC
sentry git commit: SENTRY-1853: Add the log level access mechanism
(Donghui Xu, reviewed by Alex Kolbasov)
Repository: sentry
Updated Branches:
refs/heads/master ebb94b189 -> a41a1447b
SENTRY-1853: Add the log level access mechanism (Donghui Xu, reviewed by Alex Kolbasov)
Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/a41a1447
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/a41a1447
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/a41a1447
Branch: refs/heads/master
Commit: a41a1447b206abe2129a1656faf7d28e2b9d4176
Parents: ebb94b1
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Wed Aug 23 13:53:22 2017 -0700
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Wed Aug 23 13:53:22 2017 -0700
----------------------------------------------------------------------
.../db/service/thrift/LogLevelServlet.java | 122 +++++++++++++++++++
.../db/service/thrift/SentryWebServer.java | 7 +-
.../thrift/TestSentryServerLogLevel.java | 100 +++++++++++++++
3 files changed, 226 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/sentry/blob/a41a1447/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/LogLevelServlet.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/LogLevelServlet.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/LogLevelServlet.java
new file mode 100644
index 0000000..fce41a8
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/LogLevelServlet.java
@@ -0,0 +1,122 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.sentry.provider.db.service.thrift;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
+
+public class LogLevelServlet extends HttpServlet {
+ private static final String LF = "\n";
+ private static final String BR = "<br />";
+ private static final String B_BR = "<b>%s</b><br />";
+ private static final String FORMS_HEAD =
+ "<h1>" + "Log Level" + "</h1>"
+ + LF + BR + "<hr /><h3>Results</h3>"
+ + LF + " Submitted Log Name: " + B_BR;
+ private static final String FORMS_CONTENT_GET =
+ LF + " Effective level: " + B_BR;
+ private static final String FORMS_CONTENT_SET =
+ LF + " Submitted Level: " + B_BR
+ + LF + " Setting Level to %s" + BR
+ + LF + " Effective level: " + B_BR;
+ private static final String FORMS_END =
+ LF + BR + "<hr /><h3>Get / Set</h3>"
+ + LF + "<form>Log: <input type='text' size='50' name='log' /> "
+ + "<input type='submit' value='Get Log Level' />" + "</form>"
+ + LF + "<form>Log: <input type='text' size='50' name='log' /> "
+ + "Level: <input type='text' name='level' /> "
+ + "<input type='submit' value='Set Log Level' />" + "</form>";
+ private static final String FORMS_GET = FORMS_HEAD + FORMS_CONTENT_GET;
+ private static final String FORMS_SET = FORMS_HEAD + FORMS_CONTENT_SET;
+
+ /**
+ * Return parameter on servlet request for the given name
+ *
+ * @param request: Servlet request
+ * @param name: Name of parameter in servlet request
+ * @return Parameter in servlet request for the given name, return null if can't find parameter.
+ */
+ private String getParameter(ServletRequest request, String name) {
+ String s = request.getParameter(name);
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ return s.length() == 0 ? null : s;
+ }
+
+ /**
+ * Check the validity of the log level.
+ * @param level: The log level to be checked
+ * @return
+ * true: The log level is valid
+ * false: The log level is invalid
+ */
+ private boolean isLogLevelValid(String level) {
+ return level.equals(Level.toLevel(level).toString());
+ }
+
+ /**
+ * Parse the class name and log level in the http servlet request.
+ * If the request contains only class name, return the log level in the response message.
+ * If the request contains both class name and level, set the log level to the requested level
+ * and return the setting result in the response message.
+ */
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String logName = getParameter(request, "log");
+ String level = getParameter(request, "level");
+ response.setContentType("text/html;charset=utf-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ PrintWriter out = response.getWriter();
+
+ if (logName != null) {
+ Logger logInstance = LogManager.getLogger(logName);
+ if (level == null) {
+ out.write(String.format(FORMS_GET,
+ escapeHtml(logName),
+ logInstance.getEffectiveLevel().toString()));
+ } else if (isLogLevelValid(level)) {
+ logInstance.setLevel(Level.toLevel(level));
+ out.write(String.format(FORMS_SET,
+ escapeHtml(logName),
+ level,
+ level,
+ logInstance.getEffectiveLevel().toString()));
+ } else {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid log level: " + level);
+ return;
+ }
+ }
+ out.write(FORMS_END);
+ out.close();
+ response.flushBuffer();
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/a41a1447/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
index 01f3a0d..84324c3 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryWebServer.java
@@ -104,6 +104,8 @@ public class SentryWebServer {
servletContextHandler.getServletContext()
.setAttribute(ConfServlet.CONF_CONTEXT_ATTRIBUTE, conf);
+ servletContextHandler.addServlet(new ServletHolder(LogLevelServlet.class), "/admin/logLevel");
+
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(true);
URL url = this.getClass().getResource(RESOURCE_DIR);
@@ -121,7 +123,7 @@ public class SentryWebServer {
String authMethod = conf.get(ServerConfig.SENTRY_WEB_SECURITY_TYPE);
if (!ServerConfig.SENTRY_WEB_SECURITY_TYPE_NONE.equals(authMethod)) {
- /**
+ /*
* SentryAuthFilter is a subclass of AuthenticationFilter and
* AuthenticationFilter tagged as private and unstable interface:
* While there are not guarantees that this interface will not change,
@@ -182,8 +184,7 @@ public class SentryWebServer {
throw new IllegalArgumentException("Can't use Kerberos authentication, principal ["
+ principal + "] keytab [" + keytabFile + "]", ex);
}
- LOGGER.info("Using Kerberos authentication, principal ["
- + principal + "] keytab [" + keytabFile + "]");
+ LOGGER.info("Using Kerberos authentication, principal [{}] keytab [{}]", principal, keytabFile);
}
}
}
http://git-wip-us.apache.org/repos/asf/sentry/blob/a41a1447/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerLogLevel.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerLogLevel.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerLogLevel.java
new file mode 100644
index 0000000..9e4e0a9
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerLogLevel.java
@@ -0,0 +1,100 @@
+/**
+ * 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.sentry.provider.db.service.thrift;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.sentry.service.thrift.SentryServiceIntegrationBase;
+import org.junit.*;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class TestSentryServerLogLevel extends SentryServiceIntegrationBase {
+ private final String CLASS_NAME = "org.eclipse.jetty.server.handler.ContextHandler";
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ webServerEnabled = true;
+ webSecurity = false;
+ SentryServiceIntegrationBase.setup();
+ }
+
+ @Override
+ @Before
+ public void before() throws Exception {
+ }
+
+ @Override
+ @After
+ public void after() {
+ }
+
+ /**
+ * Get the log level for the specified class
+ * @param className: Name of class
+ * @return
+ * Log level of the class
+ */
+ private String getLogLevel(String className) {
+ Logger logInstance = LogManager.getLogger(className);
+ return logInstance.getEffectiveLevel().toString();
+ }
+
+ /**
+ * Send log level and class name via the HTTP interface and verify that it is set at the loogger.
+ * @throws Exception
+ */
+ @Test
+ public void testSetLogLevel() throws Exception {
+ final URL url = new URL("http://"+ SERVER_HOST + ":" + webServerPort + "/admin/logLevel?log="
+ + CLASS_NAME + "&level=INFO");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
+ String response = IOUtils.toString(conn.getInputStream());
+ Assert.assertTrue(response.contains("INFO"));
+ Assert.assertEquals("INFO", getLogLevel(CLASS_NAME));
+ }
+
+ /**
+ * Send class name via the HTTP interface and verify that it is get at the loogger.
+ * @throws Exception
+ */
+ @Test
+ public void testGetLogLevel() throws Exception {
+ final URL url = new URL("http://"+ SERVER_HOST + ":" + webServerPort + "/admin/logLevel?log=" + CLASS_NAME);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
+ String response = IOUtils.toString(conn.getInputStream());
+ Assert.assertTrue(response.contains("INFO"));
+ Assert.assertEquals("INFO", getLogLevel(CLASS_NAME));
+ }
+
+ /**
+ * Send class name and invalid log level via the HTTP interface and verify that it returns error response.
+ * @throws Exception
+ */
+ @Test
+ public void testInvalidLogLevel() throws Exception {
+ final URL url = new URL("http://"+ SERVER_HOST + ":" + webServerPort + "/admin/logLevel?log="
+ + CLASS_NAME + "&level=ABCD");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ Assert.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, conn.getResponseCode());
+ }
+}