Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
GlogAppender.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.util;
16 
17 import java.util.Properties;
18 
19 import org.apache.log4j.AppenderSkeleton;
20 import org.apache.log4j.Level;
21 import org.apache.log4j.Logger;
22 import org.apache.log4j.PropertyConfigurator;
23 import org.apache.log4j.spi.LoggingEvent;
24 
26 import com.cloudera.impala.thrift.TLogLevel;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Preconditions;
29 
34 public class GlogAppender extends AppenderSkeleton {
35  // GLOG takes care of formatting, so we don't require a layout
36  public boolean requiresLayout() { return false; }
37 
38  // Required implementation by superclass.
39  public void ActivateOptions() { }
40 
41  // Required implementation by superclass
42  public void close() { }
43 
44  private TLogLevel levelToSeverity(Level level) {
45  Preconditions.checkState(!level.equals(Level.OFF));
46  // TODO: Level does not work well in a HashMap or switch statement due to some
47  // strangeness with equality testing.
48  if (level.equals(Level.TRACE)) return TLogLevel.VLOG_3;
49  if (level.equals(Level.ALL)) return TLogLevel.VLOG_3;
50  if (level.equals(Level.DEBUG)) return TLogLevel.VLOG;
51  if (level.equals(Level.ERROR)) return TLogLevel.ERROR;
52  if (level.equals(Level.FATAL)) return TLogLevel.FATAL;
53  if (level.equals(Level.INFO)) return TLogLevel.INFO;
54  if (level.equals(Level.WARN)) return TLogLevel.WARN;
55 
56  throw new IllegalStateException("Unknown log level: " + level.toString());
57  }
58 
59  @Override
60  public void append(LoggingEvent event) {
61  Level level = event.getLevel();
62  if (level.equals(Level.OFF)) return;
63 
64  String msg = event.getRenderedMessage();
65  if (event.getThrowableInformation() != null) {
66  msg = msg + "\nJava exception follows:\n" +
67  Joiner.on("\n").join(event.getThrowableStrRep());
68  }
69  int lineNumber = Integer.parseInt(event.getLocationInformation().getLineNumber());
70  String fileName = event.getLocationInformation().getFileName();
71  NativeLogger.LogToGlog(
72  levelToSeverity(level).getValue(), msg, fileName, lineNumber);
73  }
74 
78  private static String log4jLevelForTLogLevel(TLogLevel logLevel)
79  throws InternalException {
80  switch (logLevel) {
81  case INFO: return "INFO";
82  case WARN: return "WARN";
83  case ERROR: return "ERROR";
84  case FATAL: return "FATAL";
85  case VLOG:
86  case VLOG_2: return "DEBUG";
87  case VLOG_3: return "TRACE";
88  default: throw new InternalException("Unknown log level:" + logLevel);
89  }
90  }
91 
99  public static void Install(TLogLevel impalaLogLevel, TLogLevel otherLogLevel)
100  throws InternalException {
101  Properties properties = new Properties();
102  properties.setProperty("log4j.appender.glog", GlogAppender.class.getName());
103 
104  // These settings are relatively subtle. log4j provides many ways to filter log
105  // messages, and configuring them in the right order is a bit of black magic.
106  //
107  // The 'Threshold' property supercedes everything, so must be set to its most
108  // permissive and applies to any message sent to the glog appender.
109  //
110  // The 'rootLogger' property controls the default maximum logging level (where more
111  // verbose->larger logging level) for the entire space of classes. This will apply to
112  // all non-Impala classes, so is set to otherLogLevel.
113  //
114  // Finally we can configure per-package logging which overrides the rootLogger
115  // setting. In order to control Impala's logging independently of the rest of the
116  // world, we set the log level for com.cloudera.impala.
117  properties.setProperty("log4j.rootLogger",
118  log4jLevelForTLogLevel(otherLogLevel) + ",glog");
119  properties.setProperty("log4j.appender.glog.Threshold", "TRACE");
120  properties.setProperty("log4j.logger.com.cloudera.impala",
121  log4jLevelForTLogLevel(impalaLogLevel));
122  PropertyConfigurator.configure(properties);
123  Logger.getLogger(GlogAppender.class).info(String.format("Logging initialized. " +
124  "Impala: %s, All other: %s", impalaLogLevel, otherLogLevel));
125  }
126 };
void append(LoggingEvent event)
static String log4jLevelForTLogLevel(TLogLevel logLevel)
static void Install(TLogLevel impalaLogLevel, TLogLevel otherLogLevel)
TLogLevel levelToSeverity(Level level)