Repository: zeppelin Updated Branches: refs/heads/master 1ac0e2f00 -> 0f9a1a80c
[ZEPPELIN-3600] Add REST API to change logger level dynamically ### What is this PR for? Enabling users to change the level of a specific logger to investigate Zeppelin server's status. ### What type of PR is it? [Feature] ### Todos * [x] - Add api to change the level of logger * [x] - Add exception handler ### What is the Jira issue? * https://issues.apache.org/jira/browse/ZEPPELIN-3600 ### How should this be tested? 1. http --session ~/session.txt --form POST http://localhost:8080/api/login userName=admin password=password1 1. http --session ~/session.txt POST http://localhost:8080/api/admin name=org.apache.zeppelin.rest.AdminRestApi level=DEBUG ### Screenshots (if appropriate) ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? May be Author: Jongyoul Lee <jongy...@gmail.com> Closes #3060 from jongyoul/ZEPPELIN-3600 and squashes the following commits: 618f76074 [Jongyoul Lee] Add admin permisson to aceess /api/admin/** Change error message clearly to show a specific problem 04308bd75 [Jongyoul Lee] Change `Preconditions` to a self-check logic to throw BadRequestException Add `WebApplicationExceptionMapper` to the server Implement `ExceptionSerializer` for gson Implement `WebApplicationExceptionMapper` 5127d89b4 [Jongyoul Lee] Add api to show all loggers' name and level Add api to show a specific logger's name and level Add api to change a logger's level Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/0f9a1a80 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/0f9a1a80 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/0f9a1a80 Branch: refs/heads/master Commit: 0f9a1a80c76054c322e2d1768cf24a3e4bd49496 Parents: 1ac0e2f Author: Jongyoul Lee <jongy...@gmail.com> Authored: Wed Jul 11 16:16:43 2018 +0900 Committer: Jongyoul Lee <jongy...@apache.org> Committed: Thu Jul 12 13:43:33 2018 +0900 ---------------------------------------------------------------------- conf/shiro.ini.template | 1 + .../org/apache/zeppelin/rest/AdminRestApi.java | 82 +++++++++++++++++ .../WebApplicationExceptionMapper.java | 44 +++++++++ .../zeppelin/rest/message/LoggerRequest.java | 41 +++++++++ .../rest/message/gson/ExceptionSerializer.java | 42 +++++++++ .../rest/message/gson/LoggerSerializer.java | 52 +++++++++++ .../apache/zeppelin/server/GsonProvider.java | 93 ++++++++++++++++++++ .../apache/zeppelin/server/ZeppelinServer.java | 13 +++ .../apache/zeppelin/service/AdminService.java | 78 ++++++++++++++++ .../zeppelin/service/AdminServiceTest.java | 48 ++++++++++ 10 files changed, 494 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/conf/shiro.ini.template ---------------------------------------------------------------------- diff --git a/conf/shiro.ini.template b/conf/shiro.ini.template index 9397025..89e4785 100644 --- a/conf/shiro.ini.template +++ b/conf/shiro.ini.template @@ -116,5 +116,6 @@ admin = * /api/interpreter/** = authc, roles[admin] /api/configurations/** = authc, roles[admin] /api/credential/** = authc, roles[admin] +/api/admin/** = authc, roles[admin] #/** = anon /** = authc http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/rest/AdminRestApi.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/AdminRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/AdminRestApi.java new file mode 100644 index 0000000..093b710 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/AdminRestApi.java @@ -0,0 +1,82 @@ +/* + * 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.zeppelin.rest; + +import com.google.common.collect.Lists; +import java.util.List; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import org.apache.commons.lang.StringUtils; +import org.apache.zeppelin.annotation.ZeppelinApi; +import org.apache.zeppelin.rest.message.LoggerRequest; +import org.apache.zeppelin.service.AdminService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** This rest apis support some of feature related admin. e.g. changin log level. */ +@Path("/admin") +public class AdminRestApi { + private static final Logger logger = LoggerFactory.getLogger(AdminRestApi.class); + + private AdminService adminService; + + public AdminRestApi(AdminService adminService) { + this.adminService = adminService; + } + + /** + * It gets current loggers' name and level. + * + * @param name FQCN + * @return List of current loggers' name and level with json format. It returns all of loggers' + * name and level without name. With name, it returns only specific logger's name and level. + */ + @GET + @ZeppelinApi + public List<org.apache.log4j.Logger> getLoggerSetting(@QueryParam("name") String name) { + logger.debug("name: {}", name); + return null == name || name.isEmpty() + ? adminService.getLoggers() + : Lists.newArrayList(adminService.getLogger(name)); + } + + /** + * It change logger's level. + * + * @param loggerRequest logger's name and level with json format + * @return The changed logger's name and level. + */ + @POST + @ZeppelinApi + public List<org.apache.log4j.Logger> setLoggerLevel(LoggerRequest loggerRequest) { + if (null == loggerRequest + || StringUtils.isEmpty(loggerRequest.getName()) + || StringUtils.isEmpty(loggerRequest.getLevel())) { + logger.trace("loggerRequest: {}", loggerRequest); + throw new BadRequestException("Wrong request body"); + } + logger.debug("loggerRequest: {}", loggerRequest); + + adminService.setLoggerLevel(loggerRequest); + + return Lists.newArrayList(adminService.getLogger(loggerRequest.getName())); + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/WebApplicationExceptionMapper.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/WebApplicationExceptionMapper.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/WebApplicationExceptionMapper.java new file mode 100644 index 0000000..79e3fe0 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/WebApplicationExceptionMapper.java @@ -0,0 +1,44 @@ +/* + * 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.zeppelin.rest.exception; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.apache.zeppelin.rest.message.gson.ExceptionSerializer; + +@Provider +public class WebApplicationExceptionMapper implements ExceptionMapper<WebApplicationException> { + private final Gson gson; + + public WebApplicationExceptionMapper() { + GsonBuilder gsonBuilder = new GsonBuilder().enableComplexMapKeySerialization(); + gsonBuilder.registerTypeHierarchyAdapter( + Exception.class, new ExceptionSerializer()); + this.gson = gsonBuilder.create(); + } + + @Override + public Response toResponse(WebApplicationException exception) { + return Response.status(exception.getResponse().getStatus()) + .entity(gson.toJson(exception)).build(); + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/LoggerRequest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/LoggerRequest.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/LoggerRequest.java new file mode 100644 index 0000000..e0c80bb --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/LoggerRequest.java @@ -0,0 +1,41 @@ +/* + * 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.zeppelin.rest.message; + +public class LoggerRequest { + private String name; + private String level; + + public LoggerRequest(String name, String level) { + this.name = name; + this.level = level; + } + + public String getName() { + return name; + } + + public String getLevel() { + return level; + } + + @Override + public String toString() { + return "[name: " + name + ", level: " + level + "]"; + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/ExceptionSerializer.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/ExceptionSerializer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/ExceptionSerializer.java new file mode 100644 index 0000000..ac654c0 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/ExceptionSerializer.java @@ -0,0 +1,42 @@ +/* + * 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.zeppelin.rest.message.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import javax.ws.rs.WebApplicationException; + +public class ExceptionSerializer implements JsonSerializer<Exception> { + + @Override + public JsonElement serialize( + Exception e, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("exception", e.getClass().getSimpleName()); + jsonObject.addProperty("message", e.getMessage()); + + if (e instanceof WebApplicationException) { + jsonObject.addProperty("status", ((WebApplicationException) e).getResponse().getStatus()); + } + + return jsonObject; + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/LoggerSerializer.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/LoggerSerializer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/LoggerSerializer.java new file mode 100644 index 0000000..1d3aa47 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/gson/LoggerSerializer.java @@ -0,0 +1,52 @@ +/* + * 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.zeppelin.rest.message.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Category; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +public class LoggerSerializer implements JsonSerializer<Logger> { + + @Override + public JsonElement serialize( + Logger logger, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("name", logger.getName()); + jsonObject.addProperty("level", getLoggerLevel(logger)); + return jsonObject; + } + + private String getLoggerLevel(Category logger) { + if (null == logger) { + return StringUtils.EMPTY; + } + Level level = logger.getLevel(); + if (null != level) { + return level.toString(); + } else { + return getLoggerLevel(logger.getParent()); + } + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/server/GsonProvider.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/GsonProvider.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/GsonProvider.java new file mode 100644 index 0000000..cc14e33 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/GsonProvider.java @@ -0,0 +1,93 @@ +/* + * 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.zeppelin.server; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; +import org.apache.log4j.Logger; +import org.apache.zeppelin.rest.message.LoggerRequest; +import org.apache.zeppelin.rest.message.gson.LoggerSerializer; + +@Provider +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class GsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> { + private final Gson gson; + + public GsonProvider() { + GsonBuilder gsonBuilder = new GsonBuilder().enableComplexMapKeySerialization(); + gsonBuilder.registerTypeAdapter(Logger.class, new LoggerSerializer()); + this.gson = gsonBuilder.create(); + } + + @Override + public boolean isReadable( + Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return type == LoggerRequest.class; // For backward compatibility + } + + @Override + public T readFrom( + Class<T> type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap<String, String> httpHeaders, + InputStream entityStream) + throws IOException, WebApplicationException { + return gson.fromJson(new BufferedReader(new InputStreamReader(entityStream)), type); + } + + @Override + public boolean isWriteable( + Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return type != String.class; // Keep backward compatibility + } + + @Override + public void writeTo( + T t, + Class<?> type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) + throws IOException, WebApplicationException { + try (PrintWriter printWriter = new PrintWriter(entityStream)) { + printWriter.write(gson.toJson(t)); + printWriter.flush(); + } + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java index b699d2f..9e2c5f8 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java @@ -31,6 +31,9 @@ import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.web.env.EnvironmentLoaderListener; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.ShiroFilter; +import org.apache.zeppelin.rest.AdminRestApi; +import org.apache.zeppelin.rest.exception.WebApplicationExceptionMapper; +import org.apache.zeppelin.service.AdminService; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; @@ -429,6 +432,11 @@ public class ZeppelinServer extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); + + classes.add(GsonProvider.class); + + classes.add(WebApplicationExceptionMapper.class); + return classes; } @@ -466,6 +474,11 @@ public class ZeppelinServer extends Application { ConfigurationsRestApi settingsApi = new ConfigurationsRestApi(notebook); singletons.add(settingsApi); + AdminService adminService = new AdminService(); + + AdminRestApi adminRestApi = new AdminRestApi(adminService); + singletons.add(adminRestApi); + return singletons; } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/main/java/org/apache/zeppelin/service/AdminService.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/service/AdminService.java b/zeppelin-server/src/main/java/org/apache/zeppelin/service/AdminService.java new file mode 100644 index 0000000..2d912e2 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/service/AdminService.java @@ -0,0 +1,78 @@ +/* + * 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.zeppelin.service; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import javax.ws.rs.BadRequestException; +import org.apache.log4j.LogManager; +import org.apache.zeppelin.rest.message.LoggerRequest; + +/** This class handles all of business logic of {@link org.apache.zeppelin.rest.AdminRestApi}. */ +public class AdminService { + + public List<org.apache.log4j.Logger> getLoggers() { + Enumeration loggers = LogManager.getCurrentLoggers(); + return StreamSupport.stream( + Spliterators.spliteratorUnknownSize( + new Iterator<org.apache.log4j.Logger>() { + @Override + public boolean hasNext() { + return loggers.hasMoreElements(); + } + + @Override + public org.apache.log4j.Logger next() { + return org.apache.log4j.Logger.class.cast(loggers.nextElement()); + } + }, + Spliterator.ORDERED), + false) + .collect(Collectors.toList()); + } + + public org.apache.log4j.Logger getLogger(String name) { + return LogManager.getLogger(name); + } + + public void setLoggerLevel(LoggerRequest loggerRequest) throws BadRequestException { + try { + Class.forName(loggerRequest.getName()); + } catch (Throwable ignore) { + throw new BadRequestException( + "The class of '" + loggerRequest.getName() + "' doesn't exists"); + } + + org.apache.log4j.Logger logger = LogManager.getLogger(loggerRequest.getName()); + if (null == logger) { + throw new BadRequestException("The name of the logger is wrong"); + } + + org.apache.log4j.Level level = org.apache.log4j.Level.toLevel(loggerRequest.getLevel(), null); + if (null == level) { + throw new BadRequestException("The level of the logger is wrong"); + } + + logger.setLevel(level); + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/0f9a1a80/zeppelin-server/src/test/java/org/apache/zeppelin/service/AdminServiceTest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/service/AdminServiceTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/service/AdminServiceTest.java new file mode 100644 index 0000000..757e590 --- /dev/null +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/service/AdminServiceTest.java @@ -0,0 +1,48 @@ +/* + * 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.zeppelin.service; + +import static org.junit.Assert.assertTrue; + +import org.apache.log4j.Level; +import org.junit.Test; + +public class AdminServiceTest { + + @Test + public void testSetLoggerLevel() { + AdminService adminService = new AdminService(); + String testLoggerName = "test"; + org.apache.log4j.Logger logger = adminService.getLogger(testLoggerName); + org.apache.log4j.Level level = logger.getLevel(); + boolean setInfo = false; + if (org.apache.log4j.Level.INFO == level) { + // if a current level is INFO, set DEBUG to check if it's changed or not + logger.setLevel(org.apache.log4j.Level.DEBUG); + } else { + logger.setLevel(org.apache.log4j.Level.INFO); + setInfo = true; + } + + logger = adminService.getLogger(testLoggerName); + assertTrue( + "Level of logger should be changed", + (setInfo && org.apache.log4j.Level.INFO == logger.getLevel()) + || (!setInfo && Level.DEBUG == logger.getLevel())); + } +}