Java 中的调试级别日志记录更清晰?

发布于 2024-08-23 13:36:35 字数 655 浏览 2 评论 0原文

有没有更干净的方法让我编写调试级别日志语句?在某些方面,我们可以说字符串文字基本上是对代码进行注释并在一行中提供日志记录,并且它已经非常干净了。但在添加调试级别日志语句后,我发现代码的上下阅读变得不太容易。拿这个例子(如果我回到我的家庭电脑,我可能会更新为一个真实的例子):

int i = 0;
logger.debug("Setting i to 0,"); //Just an example, would show something more complex
i++;

InputStream is = socket.getInputStream();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

IOUtils.write(request, dos);
logger.debug("request written to output");

while (!is.read(buffer))
    logger.debug("Reading into buffer");

logger.debug("Data read completely from socket");

CustomObject.doStuff(buffer);
logger.debug("Stuff has been done to buffer");

Is there a cleaner way for me to write debug level log statements? In some ways one could say that the string literals are basically commenting the code and providing logging in one line and that it is already very clean. But after I add debug level log statements, I find the code much less easier to read up and down. Take this example (I may update to a real example if I get back to my home PC):

int i = 0;
logger.debug("Setting i to 0,"); //Just an example, would show something more complex
i++;

InputStream is = socket.getInputStream();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

IOUtils.write(request, dos);
logger.debug("request written to output");

while (!is.read(buffer))
    logger.debug("Reading into buffer");

logger.debug("Data read completely from socket");

CustomObject.doStuff(buffer);
logger.debug("Stuff has been done to buffer");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眉黛浅 2024-08-30 13:36:35

您可以尝试使用方面,尽管它们有限制,您只能将日志语句放在方法调用“周围”,即在进入和/或离开特定方法之前。

对于更详细的日志记录,恐怕除了手工编码日志消息之外没有其他方法。

一旦我确保代码按应有的方式工作(必须进行单元测试),我通常会努力从代码中删除不太需要的调试日志语句。

You could try using aspects, although these have the limitation that you can only put log statements "around" method calls, i.e. before entering and/or after leaving a specific method.

For more detailed logging, I am afraid there is no other way than hand-coded log messages.

I typically strive to remove the not-so-much-needed debug log statements from the code once I made sure that it works the way it should (for which unit tests are a must).

墨落成白 2024-08-30 13:36:35

问问自己,如果我在不同的机器/国家/星球上运行此程序,并且出现问题,而我所拥有的只是一个日志文件,我需要哪些信息才能知道出了什么问题?

谨慎在 for 循环或 while 循环中使用调试日志。例如,如果您从文件中读取 1000 条记录,则为每条记录执行一个操作。您可以在 for 循环之前记录“文件存在且可读,并将读取 1000 条记录”,并在过程完成后打印状态。如果说 1000000 条记录,那么您可以

在代码中每隔 100 或 1000 次迭代打印一些内容,除了将 i 设置为 0 的记录器之外,其他所有内容对我来说都有意义。如果记录器 statmeent 中的字符串很难计算,请注意使用 log.isDebugEnabled() 。

例如:

if(log.isDebugEnabled) {
   logger.debug("Here " + obj.aMethodCallThatTakes5MinsToEvaluateToString());
}

更新 1:SLF4J 只解决了一半的问题。

if(slfLog.isDebugEnabled) {
   slfLog.debug(obj.getObjectThatTakes5Mins());
}

是的,toString 被阻止,但如果您正在记录一个实际对象,该对象是某些计算的结果,则不会被阻止。

Ask yourself if I run this in a different machine/country/planet, and things go wrong and all I have is only a log file what information do I need to know what has gone wrong ?

Use debug logs in a for loop, or a while loop sparingly. For example, if you are reading 1000 records from a file, performing an op for each record. You could record before the for loop that "file exists and is readable and is going to read 1000 records" and print status after the process is done. If it is say 1000000 records then you could print something every say 100 or 1000 iterations

In your code except for the logger for setting i to 0 everything else sorta makes sense to me. Also care to use log.isDebugEnabled() if your string in the logger statmeent is hard to compute..

ex:

if(log.isDebugEnabled) {
   logger.debug("Here " + obj.aMethodCallThatTakes5MinsToEvaluateToString());
}

UPDATE 1: SLF4J solves only half the problem.

if(slfLog.isDebugEnabled) {
   slfLog.debug(obj.getObjectThatTakes5Mins());
}

Yes the toString is prevented but if you are logging an actual object which is result of some computation you are not prevented.

烂人 2024-08-30 13:36:35

如果您想要非常细粒度的调试指令,我不确定您是否可以将实际代码与调试代码分开。

如果您想要更高的级别,也许使用 AOP 添加日志记录可能有助于使为了更容易阅读,也许使用 代理 对象?

但是,如果您的调试指令与您提供的示例一样细粒度,恕我直言,您可以通过用单元测试替换记录器来获得更多收益。不要在日志中写下发生了什么事情,而是测试它确实发生了。

If you want very fine grained debug instructions I am not sure you can separate the actual code from the debug code.

If you want it at a higher level, maybe adding your logging using AOP could help make things easier to read, maybe use a proxy object?

But if you have debug instructions as fine grained as in the example you provided, IMHO you could gain more by replacing the loggers with unit tests. Don't write in a log that something happened, test that it did.

烦人精 2024-08-30 13:36:35

如果您不喜欢日志语句,您将无法做很多事情。信息需要以某种方式存在。

你能做的就是认真考虑那里需要什么。您基本上是为日志文件阅读器编写的,根据定义,日志文件阅读器不知道您的程序如何工作,因此信息需要简洁且正确。就我个人而言,我经常将方法名称添加到日志语句中。

另请注意,slf4j 允许您使用 {} 语法,这在一定程度上有所帮助。

 log.debug("main() date={}, args={}", new java.util.Date(), args);

另请注意,通过单元测试,您可以将很多内容移动到那里,因为您知道它可以工作。

You will not be able to do much if you dislike the log statements. The information needs to be there somehow.

What you CAN do, is strongly considering what NEEDS to be there. You are basically writing for the log file reader who per definition does not know about how your program works, so the information needs to be concise and correct. Personally I very frequently add the method name to the log statement.

Also note that slf4j allows you to use the {}-syntax which helps somewhat

 log.debug("main() date={}, args={}", new java.util.Date(), args);

Also note that having unit tests, allow you to move much stuff to there simply because you know that THAT works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文