闲谈程序中如何打印log
2015-01-16 10:28
211 查看
程序中记录日志一般有两个目的:Troubleshooting和显示程序运行状态。好的日志记录方式可以提供我们足够多定位问题的依据。
这周看过很多代码,对里面的日志记录方式有些想法,今天是周末,也想总结下我对这个问题的看法。日志记录大家都会认为简单,但如何通过日志可以高效定位问题可不是简单的事情。这里我会写下面三个方面的内容,主要是举例为主,提醒我以后得注意这些方面
怎样记日志可以方便Troubleshooting
程序运行状态可以记哪些
应该避免怎样的日志方式
方便Troubleshooting的日志:
对外部的调用封装:
程序中对外部系统与模块的依赖调用前后都记下日志,方便接口调试。出问题时也可以很快理清是哪块的问题
Java代码
LOG.debug("Calling external system:" + parameters);
Object result = null;
try {
result = callRemoteSystem(params);
LOG.debug("Called successfully. result is " + result);
} catch (Exception e) {
LOG.warn("Failed at calling xxx system . exception : " + e);
}
状态变化:
程序中重要的状态信息的变化应该记录下来,方便查问题时还原现场,推断程序运行过程
Java代码
boolean isRunning;
isRunning = true;
LOG.info("System is running");
//...
isRunning = false;
LOG.info("System was interrupted by " + Thread.currentThread().getName());
系统入口与出口:
这个粒度可以是重要方法级或模块级。记录它的输入与输出,方便定位
Java代码
void execute(Object input) {
LOG.debug("Invoke parames : " + input);
Object result = null;
//business logical
LOG.debug("Method result : " + result);
}
业务异常:
任何业务异常都应该记下来
Java代码
try { //business logical } catch (IOException e) { LOG.warn("Description xxx" , e); } catch (BusinessException e) { LOG.warn("Let me know anything"); } catch (Exception e) { LOG.error("Description xxx", e); } void invoke(Object primaryParam) { if (primaryParam == null) { LOG.warn("Why this primary param is null?"); return; } }
非预期执行:
为程序在“有可能”执行到的地方打印日志。如果我想删除一个文件,结果返回成功。但事实上,那个文件在你想删除之前就不存在了。最终结果是一致的,但程序得让我们知道这种情况,要查清为什么文件在删除之前就已经不存在呢
Java代码
int myValue = xxxx;
int absResult = Math.abs(myValue);
if (absResult < 0) {
LOG.info("Original int " + myValue + "has nagetive abs " + absResult);
}
很少出现的else情况:
else可能吞掉你的请求,或是赋予难以理解的最终结果
Java代码
Object result = null; if (running) { result = xxx; } else { result = yyy; LOG.debug("System does not running, we change the final result"); }
程序运行状态
程序在运行时就像一个机器人,我们可以从它的日志看出它正在做什么,是不是按预期的设计在做,所以这些正常的运行状态是要有的。
程序运行时间:
Java代码
long startTime = System.currentTime();
// business logical
LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms");
大批量数据的执行进度:
Java代码
LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");
关键变量及正在做哪些重要的事情:
执行关键的逻辑,做IO操作等等
Java代码
String getJVMPid() {
String pid = "";
// Obtains JVM process ID
LOG.info("JVM pid is " + pid);
return pid;
}
void invokeRemoteMethod(Object params) {
LOG.info("Calling remote method : " + params);
//Calling remote server
}
避免的日志方式
无意义的Log:
日志不包含有意义的信息: 你肯定想知道的是哪个文件不存在吧
Java代码
File file = new File("xxx"); if (!file.isExist()) { LOG.warn("File does not exist"); //Useless message }
混淆信息的Log:
日志应该是清晰准确的: 当看到日志的时候,你知道是因为连接池取不到连接导致的问题么?
Java代码
Connection connection = ConnectionFactory.getConnection();
if (connection == null) {
LOG.warn("System initialized unsuccessfully");
}
这周看过很多代码,对里面的日志记录方式有些想法,今天是周末,也想总结下我对这个问题的看法。日志记录大家都会认为简单,但如何通过日志可以高效定位问题可不是简单的事情。这里我会写下面三个方面的内容,主要是举例为主,提醒我以后得注意这些方面
怎样记日志可以方便Troubleshooting
程序运行状态可以记哪些
应该避免怎样的日志方式
方便Troubleshooting的日志:
对外部的调用封装:
程序中对外部系统与模块的依赖调用前后都记下日志,方便接口调试。出问题时也可以很快理清是哪块的问题
Java代码
LOG.debug("Calling external system:" + parameters);
Object result = null;
try {
result = callRemoteSystem(params);
LOG.debug("Called successfully. result is " + result);
} catch (Exception e) {
LOG.warn("Failed at calling xxx system . exception : " + e);
}
LOG.debug("Calling external system:" + parameters); Object result = null; try { result = callRemoteSystem(params); LOG.debug("Called successfully. result is " + result); } catch (Exception e) { LOG.warn("Failed at calling xxx system . exception : " + e); }
状态变化:
程序中重要的状态信息的变化应该记录下来,方便查问题时还原现场,推断程序运行过程
Java代码
boolean isRunning;
isRunning = true;
LOG.info("System is running");
//...
isRunning = false;
LOG.info("System was interrupted by " + Thread.currentThread().getName());
boolean isRunning; isRunning = true; LOG.info("System is running"); //... isRunning = false; LOG.info("System was interrupted by " + Thread.currentThread().getName());
系统入口与出口:
这个粒度可以是重要方法级或模块级。记录它的输入与输出,方便定位
Java代码
void execute(Object input) {
LOG.debug("Invoke parames : " + input);
Object result = null;
//business logical
LOG.debug("Method result : " + result);
}
void execute(Object input) { LOG.debug("Invoke parames : " + input); Object result = null; //business logical LOG.debug("Method result : " + result); }
业务异常:
任何业务异常都应该记下来
Java代码
try { //business logical } catch (IOException e) { LOG.warn("Description xxx" , e); } catch (BusinessException e) { LOG.warn("Let me know anything"); } catch (Exception e) { LOG.error("Description xxx", e); } void invoke(Object primaryParam) { if (primaryParam == null) { LOG.warn("Why this primary param is null?"); return; } }
try { //business logical } catch (IOException e) { LOG.warn("Description xxx" , e); } catch (BusinessException e) { LOG.warn("Let me know anything"); } catch (Exception e) { LOG.error("Description xxx", e); } void invoke(Object primaryParam) { if (primaryParam == null) { LOG.warn("Why this primary param is null?"); return; } }
非预期执行:
为程序在“有可能”执行到的地方打印日志。如果我想删除一个文件,结果返回成功。但事实上,那个文件在你想删除之前就不存在了。最终结果是一致的,但程序得让我们知道这种情况,要查清为什么文件在删除之前就已经不存在呢
Java代码
int myValue = xxxx;
int absResult = Math.abs(myValue);
if (absResult < 0) {
LOG.info("Original int " + myValue + "has nagetive abs " + absResult);
}
int myValue = xxxx; int absResult = Math.abs(myValue); if (absResult < 0) { LOG.info("Original int " + myValue + "has nagetive abs " + absResult); }
很少出现的else情况:
else可能吞掉你的请求,或是赋予难以理解的最终结果
Java代码
Object result = null; if (running) { result = xxx; } else { result = yyy; LOG.debug("System does not running, we change the final result"); }
Object result = null; if (running) { result = xxx; } else { result = yyy; LOG.debug("System does not running, we change the final result"); }
程序运行状态
程序在运行时就像一个机器人,我们可以从它的日志看出它正在做什么,是不是按预期的设计在做,所以这些正常的运行状态是要有的。
程序运行时间:
Java代码
long startTime = System.currentTime();
// business logical
LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms");
long startTime = System.currentTime(); // business logical LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms");
大批量数据的执行进度:
Java代码
LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");
LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");
关键变量及正在做哪些重要的事情:
执行关键的逻辑,做IO操作等等
Java代码
String getJVMPid() {
String pid = "";
// Obtains JVM process ID
LOG.info("JVM pid is " + pid);
return pid;
}
void invokeRemoteMethod(Object params) {
LOG.info("Calling remote method : " + params);
//Calling remote server
}
String getJVMPid() { String pid = ""; // Obtains JVM process ID LOG.info("JVM pid is " + pid); return pid; } void invokeRemoteMethod(Object params) { LOG.info("Calling remote method : " + params); //Calling remote server }
避免的日志方式
无意义的Log:
日志不包含有意义的信息: 你肯定想知道的是哪个文件不存在吧
Java代码
File file = new File("xxx"); if (!file.isExist()) { LOG.warn("File does not exist"); //Useless message }
File file = new File("xxx"); if (!file.isExist()) { LOG.warn("File does not exist"); //Useless message }
混淆信息的Log:
日志应该是清晰准确的: 当看到日志的时候,你知道是因为连接池取不到连接导致的问题么?
Java代码
Connection connection = ConnectionFactory.getConnection();
if (connection == null) {
LOG.warn("System initialized unsuccessfully");
}
相关文章推荐
- 闲谈程序中如何打印log
- 如何在程序中写log日志(定义log级别:error,warn, info, debug; 宏定义打印不同级别的日志; 程序中引用宏定义即可)
- 一个很好的打印程序log到文件的类
- 如何在Opencore的log打印方式
- 程序中如何打印日志?(一)
- 程序中log打印的梳理
- 简单的程序日志打印函数WriteLog,适用于vc等,含宽字符。
- 如何在ASP程序中打印Excel报表(无组件的经典程序)
- MTK平台,如何开启UART打印log到终端
- 程序员应该如何打印log日志
- 如何在eclipse dump Java内存占用情况和打印GC LOG
- 如何写一个可以设置等级的打印log,类似于 Debug版本 和release版本。
- 如何获取android程序LOG
- 如何把 Visutal studio中的“print-on-breakpoint”消息打印在程序的任何地方
- 如何在代码里打印程序所占用的内存
- 程序中如何打印日志?(三) VC++6.0和BCB6.0都不支持变长参数的宏
- 【转】如何读取程序的Log信息
- 如何读取程序的Log信息
- Metro开发中,C#的工程如何打印它所包含的c++的dll的log信息
- flex程序打印log日志,trace信息