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  private static void invoke(Method method, Object... args) throws AssertionError {
062    try {
063      method.invoke(null, args);
064    } catch (IllegalAccessException e) {
065      throw new AssertionError("should not happen", e);
066    } catch (InvocationTargetException e) {
067      throwUnchecked(e.getCause());
068      throw new AssertionError("should not happen", e.getCause());
069    }
070  }
071
072  public static void setAllLevels(String loggerName, String levelName) {
073    Method method = getMethod("setAllLevels", String.class, String.class);
074    invoke(method, loggerName, levelName);
075  }
076
077  public static void setLogLevel(String loggerName, String levelName) {
078    Method method = getMethod("setLogLevel", String.class, String.class);
079    invoke(method, loggerName, levelName);
080  }
081
082  public static void setRootLevel(String levelName) {
083    Method method = getMethod("setRootLevel", String.class);
084    invoke(method, levelName);
085  }
086
087  public static String getEffectiveLevel(String loggerName) {
088    Method method = getMethod("getEffectiveLevel", String.class);
089    try {
090      return (String) method.invoke(null, loggerName);
091    } catch (IllegalAccessException e) {
092      throw new AssertionError("should not happen", e);
093    } catch (InvocationTargetException e) {
094      throwUnchecked(e.getCause());
095      throw new AssertionError("should not happen", e.getCause());
096    }
097  }
098
099  @SuppressWarnings("unchecked")
100  public static Set<File> getActiveLogFiles() throws IOException {
101    Method method = getMethod("getActiveLogFiles");
102    try {
103      return (Set<File>) method.invoke(null);
104    } catch (IllegalAccessException e) {
105      throw new AssertionError("should not happen", e);
106    } catch (InvocationTargetException e) {
107      Throwable cause = e.getCause();
108      throwUnchecked(cause);
109      if (cause instanceof IOException) {
110        throw (IOException) cause;
111      }
112      throw new AssertionError("should not happen", cause);
113    }
114  }
115
116  /**
117   * Disables Zk- and HBase client logging
118   */
119  public static void disableZkAndClientLoggers() {
120    // disable zookeeper log to avoid it mess up command output
121    setLogLevel("org.apache.zookeeper", "OFF");
122    // disable hbase zookeeper tool log to avoid it mess up command output
123    setLogLevel("org.apache.hadoop.hbase.zookeeper", "OFF");
124    // disable hbase client log to avoid it mess up command output
125    setLogLevel("org.apache.hadoop.hbase.client", "OFF");
126  }
127
128  /**
129   * Switches the logger for the given class to DEBUG level.
130   * @param clazz The class for which to switch to debug logging.
131   */
132  public static void enableDebug(Class<?> clazz) {
133    setLogLevel(clazz.getName(), "DEBUG");
134  }
135}