在debug hive的问题时,我们经常需要在源码里面增加必要的日志信息,来跟踪变量的变化或者是方法执行的情况,性能等。。hive里面有下面几个日志的实现方式。
1种是常用的通过
org.apache.commons.logging.Log
和
org.apache.commons.logging.LogFactory
类实现的。比如要打印类的info信息时,只需要下面这样就可以。
staticfinalprivateLogLOG=LogFactory.getLog(CLASS_NAME)LOG.info(“xxxxxx”);
如果要跟踪一个方法的执行时间,只需要在在方法调用前后各加一条日志信息记录当前时间戳,然后取差值即可。
另一种是LogHelper
org.apache.hadoop.hive.ql.session.SessionState.LogHelper
LogHelper类是SessionState的内部类
输出日志最终调用的是LOG.xxx和对应日志输出的println方法(比如System.out.println/log4j等)
但是日志只有两个级别,info和error。
以printInfo方法为例,具体实现:
publicvoidprintInfo(Stringinfo,Stringdetail){if(!getIsSilent()){getInfoStream().println(info);}LOG.info(info+StringUtils.defaultString(detail));//调用LOG.info(即第一种方法)}
使用的sample:
staticfinalprivateLogHelperconsole=newLogHelper(LOG);console.printError(“Authorizationfailed:”+authExp.getMessage()+”.UseSHOWGRANTtogetmoredetails.”);
还有一种重要的类是PerfLogger类,可以实现记录方法执行时间的信息,,在一些情况下可以取代第一种记录性能的方法。
PerfLogger类主要是用在Driver类的compile方法中,用来记录各个step使用的时间。
看下具体实现:
首先声明存储starttime和endtime的map:
protectedfinalMap<String,Long>startTimes=newHashMap<String,Long>();protectedfinalMap<String,Long>endTimes=newHashMap<String,Long>();
主要方法:
1).构造方法可以传入一个boolean参数,控制是否reset(默认是false)
protectedstaticfinalThreadLocal<PerfLogger>perfLogger=newThreadLocal<PerfLogger>();publicstaticPerfLoggergetPerfLogger(booleanresetPerfLogger){if(SessionState.get()==null){if(perfLogger.get()==null||resetPerfLogger){perfLogger.set(newPerfLogger());}returnperfLogger.get();}else{returnSessionState.get().getPerfLogger(resetPerfLogger);}}
2).PerfLogBegin 用来记录开始时间,主要是使用了LOG.info(第一种记录日志的方法)
publicvoidPerfLogBegin(StringcallerName,Stringmethod){longstartTime=System.currentTimeMillis();LOG.info(“<PERFLOGmethod=”+method+”from=”+callerName+”>”);startTimes.put(method,newLong(startTime));//将方法和对应的startTime放在startTimes的map中}
3).相应的PerfLogEnd用来记录结束时间
publiclongPerfLogEnd(StringcallerName,Stringmethod){LongstartTime=startTimes.get(method);longendTime=System.currentTimeMillis();longduration=-1;endTimes.put(method,newLong(endTime));StringBuildersb=newStringBuilder(“</PERFLOGmethod=”).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);returnduration;}
getStartTime和getEndTime分别通过对应的map来获取starttime和endtime
唯有讲述此间途经的美景,分享没有男主角的相片。