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.logging;
019
020import java.io.File;
021import java.io.IOException;
022import java.lang.reflect.InvocationTargetException;
023import java.lang.reflect.Method;
024import java.util.Set;
025import org.apache.yetus.audience.InterfaceAudience;
026
027/**
028 * A bridge class for operating on log4j, such as changing log level, etc.
029 * <p/>
030 * Will call the methods in {@link InternalLog4jUtils} to actually operate on the log4j stuff.
031 */
032@InterfaceAudience.Private
033public final class Log4jUtils {
034
035  private static final String INTERNAL_UTILS_CLASS_NAME =
036    "org.apache.hadoop.hbase.logging.InternalLog4jUtils";
037
038  private Log4jUtils() {
039  }
040
041  // load class when calling to avoid introducing class not found exception on log4j when loading
042  // this class even without calling any of the methods below.
043  private static Method getMethod(String methodName, Class<?>... args) {
044    try {
045      Class<?> clazz = Class.forName(INTERNAL_UTILS_CLASS_NAME);
046      return clazz.getDeclaredMethod(methodName, args);
047    } catch (ClassNotFoundException | NoSuchMethodException e) {
048      throw new AssertionError("should not happen", e);
049    }
050  }
051
052  private static void throwUnchecked(Throwable throwable) {
053    if (throwable instanceof RuntimeException) {
054      throw (RuntimeException) throwable;
055    }
056    if (throwable instanceof Error) {
057      throw (Error) throwable;
058    }
059  }
060
061  public static void setLogLevel(String loggerName, String levelName) {
062    Method method = getMethod("setLogLevel", String.class, String.class);
063    try {
064      method.invoke(null, loggerName, levelName);
065    } catch (IllegalAccessException e) {
066      throw new AssertionError("should not happen", e);
067    } catch (InvocationTargetException e) {
068      throwUnchecked(e.getCause());
069      throw new AssertionError("should not happen", e.getCause());
070    }
071  }
072
073  public static String getEffectiveLevel(String loggerName) {
074    Method method = getMethod("getEffectiveLevel", String.class);
075    try {
076      return (String) method.invoke(null, loggerName);
077    } catch (IllegalAccessException e) {
078      throw new AssertionError("should not happen", e);
079    } catch (InvocationTargetException e) {
080      throwUnchecked(e.getCause());
081      throw new AssertionError("should not happen", e.getCause());
082    }
083  }
084
085  @SuppressWarnings("unchecked")
086  public static Set<File> getActiveLogFiles() throws IOException {
087    Method method = getMethod("getActiveLogFiles");
088    try {
089      return (Set<File>) method.invoke(null);
090    } catch (IllegalAccessException e) {
091      throw new AssertionError("should not happen", e);
092    } catch (InvocationTargetException e) {
093      Throwable cause = e.getCause();
094      throwUnchecked(cause);
095      if (cause instanceof IOException) {
096        throw (IOException) cause;
097      }
098      throw new AssertionError("should not happen", cause);
099    }
100  }
101
102  /**
103   * Disables Zk- and HBase client logging
104   */
105  public static void disableZkAndClientLoggers() {
106    // disable zookeeper log to avoid it mess up command output
107    setLogLevel("org.apache.zookeeper", "OFF");
108    // disable hbase zookeeper tool log to avoid it mess up command output
109    setLogLevel("org.apache.hadoop.hbase.zookeeper", "OFF");
110    // disable hbase client log to avoid it mess up command output
111    setLogLevel("org.apache.hadoop.hbase.client", "OFF");
112  }
113
114  /**
115   * Switches the logger for the given class to DEBUG level.
116   * @param clazz The class for which to switch to debug logging.
117   */
118  public static void enableDebug(Class<?> clazz) {
119    setLogLevel(clazz.getName(), "DEBUG");
120  }
121}