博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hive中打印日志的几种方式实现
阅读量:6122 次
发布时间:2019-06-21

本文共 5791 字,大约阅读时间需要 19 分钟。

在debug hive的问题时,我们经常需要在源码里面增加必要的日志信息,来跟踪变量的变化或者是方法执行的情况,性能等。。hive里面有下面几个日志的实现方式。

1种是常用的通过

1
org.apache.commons.logging.Log

1
org.apache.commons.logging.LogFactory

类实现的。

比如要打印类的info信息时,只需要下面这样就可以。

1
2
static 
final 
private 
Log LOG = LogFactory.getLog(CLASS_NAME)
LOG.info(
"xxxxxx"
);

如果要跟踪一个方法的执行时间,只需要在在方法调用前后各加一条日志信息记录当前时间戳,然后取差值即可。

另一种是LogHelper

1
org.apache.hadoop.hive.ql.session.SessionState.LogHelper

LogHelper类是SessionState的内部类

输出日志最终调用的是LOG.xxx和对应日志输出的println方法(比如System.out.println/log4j等)

但是日志只有两个级别,info和error。

以printInfo方法为例,具体实现:

1
2
3
4
5
6
    
public 
void 
printInfo(String info, String detail) {
      
if 
(!getIsSilent()) {
        
getInfoStream().println(info);
      
}
      
LOG.info(info + StringUtils.defaultString(detail));  
//调用LOG.info(即第一种方法)
    
}

使用的sample:

1
2
static 
final 
private 
LogHelper console = 
new 
LogHelper (LOG);
console.printError(
"Authorization failed:" 
+ authExp.getMessage() + 
". Use SHOW GRANT to get more details." 
);

还有一种重要的类是PerfLogger类,可以实现记录方法执行时间的信息,在一些情况下可以取代第一种记录性能的方法。

PerfLogger类主要是用在Driver类的compile方法中,用来记录各个step使用的时间。

看下具体实现:

首先声明存储starttime和endtime的map:

1
2
 
protected 
final 
Map<String, Long> startTimes = 
new 
HashMap<String, Long>();
 
protected 
final 
Map<String, Long> endTimes = 
new 
HashMap<String, Long>();

主要方法:

1).构造方法可以传入一个boolean参数,控制是否reset(默认是false)

1
2
3
4
5
6
7
8
9
10
11
  
protected 
static 
final 
ThreadLocal<PerfLogger> perfLogger = 
new 
ThreadLocal<PerfLogger>();
  
public 
static 
PerfLogger getPerfLogger(
boolean 
resetPerfLogger) {
    
if 
(SessionState.get() == 
null
) {
      
if 
(perfLogger.get() == 
null 
|| resetPerfLogger) {
        
perfLogger.set(
new 
PerfLogger());
      
}
      
return 
perfLogger.get();
    
else 
{
      
return 
SessionState.get().getPerfLogger(resetPerfLogger);
    
}
  
}

2).PerfLogBegin 用来记录开始时间,主要是使用了LOG.info(第一种记录日志的方法)

1
2
3
4
5
  
public 
void 
PerfLogBegin(String callerName, String method) {
    
long 
startTime = System.currentTimeMillis();
    
LOG.info( 
"<PERFLOG method=" 
+ method + 
" from=" 
+ callerName + 
">"
); 
    
startTimes.put(method, 
new 
Long(startTime));  
//将方法和对应的startTime放在startTimes的map中
  
}

3).相应的PerfLogEnd用来记录结束时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
public 
long 
PerfLogEnd(String callerName, String method) {
    
Long startTime = startTimes.get(method);
    
long 
endTime = System. currentTimeMillis();
    
long 
duration = -
1
;
    
endTimes.put(method, 
new 
Long(endTime));
    
StringBuilder sb = 
new 
StringBuilder(
"</PERFLOG method=" 
).append(method); 
    
if 
(startTime != 
null
) {
      
sb.append( 
" start="
).append(startTime);
    
}
    
sb.append(
" end="
).append(endTime);
    
if 
(startTime != 
null
) {
      
duration = endTime - startTime.longValue();
      
sb.append( 
" duration="
).append(duration);
    
}
    
sb.append(
" from="
).append(callerName).append( 
">"
);
    
LOG.info(sb); 
    
return 
duration;
  
}

getStartTime和getEndTime分别通过对应的map来获取starttime和endtime

4.是不是所有的method都可以用这种方法获取执行的性能?答案是no,在PerfLogger类中定义了部分属性,对应于method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  
public 
static 
final 
String ACQUIRE_READ_WRITE_LOCKS = 
"acquireReadWriteLocks"
;
  
public 
static 
final 
String COMPILE = 
"compile"
;
  
public 
static 
final 
String PARSE = 
"parse"
;
  
public 
static 
final 
String ANALYZE = 
"semanticAnalyze"
;
  
public 
static 
final 
String DO_AUTHORIZATION = 
"doAuthorization"
;
  
public 
static 
final 
String DRIVER_EXECUTE = 
"Driver.execute"
;
  
public 
static 
final 
String INPUT_SUMMARY = 
"getInputSummary"
;
  
public 
static 
final 
String GET_SPLITS = 
"getSplits"
;
  
public 
static 
final 
String RUN_TASKS = 
"runTasks"
;
  
public 
static 
final 
String SERIALIZE_PLAN = 
"serializePlan"
;
  
public 
static 
final 
String DESERIALIZE_PLAN = 
"deserializePlan"
;
  
public 
static 
final 
String CLONE_PLAN = 
"clonePlan"
;
  
public 
static 
final 
String TASK = 
"task."
;
  
public 
static 
final 
String RELEASE_LOCKS = 
"releaseLocks"
;
  
public 
static 
final 
String PRUNE_LISTING = 
"prune-listing"
;
  
public 
static 
final 
String PARTITION_RETRIEVING = 
"partition-retrieving"
;
  
public 
static 
final 
String PRE_HOOK = 
"PreHook."
;
  
public 
static 
final 
String POST_HOOK = 
"PostHook."
;
  
public 
static 
final 
String FAILURE_HOOK = 
"FailureHook."
;
  
public 
static 
final 
String DRIVER_RUN = 
"Driver.run"
;
  
public 
static 
final 
String TIME_TO_SUBMIT = 
"TimeToSubmit"
;
  
public 
static 
final 
String TEZ_SUBMIT_TO_RUNNING = 
"TezSubmitToRunningDag"
;
  
public 
static 
final 
String TEZ_BUILD_DAG = 
"TezBuildDag"
;
  
public 
static 
final 
String TEZ_SUBMIT_DAG = 
"TezSubmitDag"
;
  
public 
static 
final 
String TEZ_RUN_DAG = 
"TezRunDag"
;
  
public 
static 
final 
String TEZ_CREATE_VERTEX = 
"TezCreateVertex."
;
  
public 
static 
final 
String TEZ_RUN_VERTEX = 
"TezRunVertex."
;
  
public 
static 
final 
String TEZ_INITIALIZE_PROCESSOR = 
"TezInitializeProcessor"
;
  
public 
static 
final 
String TEZ_RUN_PROCESSOR = 
"TezRunProcessor"
;
  
public 
static 
final 
String TEZ_INIT_OPERATORS = 
"TezInitializeOperators"
;
  
public 
static 
final 
String LOAD_HASHTABLE = 
"LoadHashtable"
;
  
public 
static 
final 
String ORC_GET_SPLITS = 
"OrcGetSplits"
;

再来看一下其调用方式:

1
2
3
4
5
6
7
8
9
10
比如org.apache.hadoop.hive.ql.Driver类中的compile方法:
static 
final 
private 
String CLASS_NAME = Driver. 
class
.getName();
  
public 
int 
compile(String command, 
boolean 
resetTaskIds) {
    
PerfLogger perfLogger = PerfLogger.getPerfLogger(); 
//实例化一个PerfLogger的对象
.......
      
perfLogger.PerfLogBegin( CLASS_NAME, PerfLogger.PARSE);  
//记录开始时间,传入本类的类名记录的方法(方法对应了PerfLogger类中对应的属性)
      
ParseDriver pd = 
new 
ParseDriver();
      
ASTNode tree = pd.parse(command, ctx);
      
tree = ParseUtils.findRootNonNullToken(tree);
      
perfLogger.PerfLogEnd( CLASS_NAME, PerfLogger.PARSE);

记录parse消耗时间的对应日志:

1
2
3
14
/
07
/
31 
14
:
33
:
21 
INFO log.PerfLogger: <PERFLOG method=parse from=org.apache.hadoop.hive.ql.Driver>
.....
14
/
07
/
31 
14
:
33
:
21 
INFO log.PerfLogger: </PERFLOG method=parse start=
1406788401914 
end=
1406788401916 
duration=
2 
from=org.apache.hadoop.hive.ql.Driver>

3种方法可以根据需要选择使用。

本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1541771,如需转载请自行联系原作者

你可能感兴趣的文章
Java面试常考知识点
查看>>
Python并发编程一(多进程)
查看>>
全世界78707个主要城市信息数据库,包含经纬度坐标值 转
查看>>
北京医院排名 很有用,留下了
查看>>
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
查看>>
CSS实例(一)下拉菜单
查看>>
C#---HttpWebRequest+HttpWebResponse实现登录人人网
查看>>
HDU 2444 The Accomodation of Students(BFS判断是否为二分图)
查看>>
[MongoDB]可视化工具Robomongo
查看>>
[java web]Idea+maven+spring4+hibernate5+struts2整合过程
查看>>
CODEVS 1073 家族
查看>>
【BZOJ 1085】 [SCOI2005]骑士精神
查看>>
Fedora 16 安装 Mp3和视频播放器
查看>>
老白关于rac性能调优的建议(10gRAC)
查看>>
数据库面试系列之六:会写基本的sql语句
查看>>
java如何加载不同环境的properties配置文件?
查看>>
小米Git
查看>>
好的技术团队和差的技术团队的区别在于技术架构前瞻性和适应变化的能力
查看>>
jenkins+Maven+Jmeter
查看>>
JavaScript核心基础学习目录
查看>>