Optimal Logging
by Anthony Vallone
Channeling Goldilocks
Never log too much. Massive, disk-quota burning logs are a clear indicator that little thought was put in to logging. If you log too much, you’ll need to devise complex approaches to minimize disk access, maintain log history, archive large quantities of data, and query these large sets of data. More importantly, you’ll make it very difficult to find valuable information in all the chatter.
The only thing worse than logging too much is logging too little. There are normally two main goals of logging: help with bug investigation and event confirmation. If your log can’t explain the cause of a bug or whether a certain transaction took place, you are logging too little.
Good things to log:
- Important startup configuration
- Errors
- Warnings
- Changes to persistent data
- Requests and responses between major system components
- Significant state changes
- User interactions
- Calls with a known risk of failure
- Waits on conditions that could take measurable time to satisfy
- Periodic progress during long-running tasks
- Significant branch points of logic and conditions that led to the branch
- Summaries of processing steps or events from high level functions - Avoid logging every step of a complex process in low-level functions.
Bad things to log:
- Function entry - Don’t log a function entry unless it is significant or logged at the debug level.
- Data within a loop - Avoid logging from many iterations of a loop. It is OK to log from iterations of small loops or to log periodically from large loops.
- Content of large messages or files - Truncate or summarize the data in some way that will be useful to debugging.
- Benign errors - Errors that are not really errors can confuse the log reader. This sometimes happens when exception handling is part of successful execution flow.
- Repetitive errors - Do not repetitively log the same or similar error. This can quickly fill a log and hide the actual cause. Frequency of error types is best handled by monitoring. Logs only need to capture detail for some of those errors.
There is More Than One Level
Don't log everything at the same log level. Most logging libraries offer several log levels, and you can enable certain levels at system startup. This provides a convenient control for log verbosity.
The classic levels are:
- Debug - verbose and only useful while developing and/or debugging.
- Info - the most popular level.
- Warning - strange or unexpected states that are acceptable.
- Error - something went wrong, but the process can recover.
- Critical - the process cannot recover, and it will shutdown or restart.
Practically speaking, only two log configurations are needed:
- Production - Every level is enabled except debug. If something goes wrong in production, the logs should reveal the cause.
- Development & Debug - While developing new code or trying to reproduce a production issue, enable all levels.
Test Logs Are Important Too
Log quality is equally important in test and production code. When a test fails, the log should clearly show whether the failure was a problem with the test or production system. If it doesn't, then test logging is broken.
Test logs should always contain:
- Test execution environment
- Initial state
- Setup steps
- Test case steps
- Interactions with the system
- Expected results
- Actual results
- Teardown steps
Conditional Verbosity With Temporary Log Queues
When errors occur, the log should contain a lot of detail. Unfortunately, detail that led to an error is often unavailable once the error is encountered. Also, if you’ve followed advice about not logging too much, your log records prior to the error record may not provide adequate detail. A good way to solve this problem is to create temporary, in-memory log queues. Throughout processing of a transaction, append verbose details about each step to the queue. If the transaction completes successfully, discard the queue and log a summary. If an error is encountered, log the content of the entire queue and the error. This technique is especially useful for test logging of system interactions.
Failures and Flakiness Are Opportunities
When production problems occur, you’ll obviously be focused on finding and correcting the problem, but you should also think about the logs. If you have a hard time determining the cause of an error, it's a great opportunity to improve your logging. Before fixing the problem, fix your logging so that the logs clearly show the cause. If this problem ever happens again, it’ll be much easier to identify.
If you cannot reproduce the problem, or you have a flaky test, enhance the logs so that the problem can be tracked down when it happens again.
Using failures to improve logging should be used throughout the development process. While writing new code, try to refrain from using debuggers and only use the logs. Do the logs describe what is going on? If not, the logging is insufficient.
Might As Well Log Performance Data
Logged timing data can help debug performance issues. For example, it can be very difficult to determine the cause of a timeout in a large system, unless you can trace the time spent on every significant processing step. This can be easily accomplished by logging the start and finish times of calls that can take measurable time:
- Significant system calls
- Network requests
- CPU intensive operations
- Connected device interactions
- Transactions
Following the Trail Through Many Threads and Processes
You should create unique identifiers for transactions that involve processing across many threads and/or processes. The initiator of the transaction should create the ID, and it should be passed to every component that performs work for the transaction. This ID should be logged by each component when logging information about the transaction. This makes it much easier to trace a specific transaction when many transactions are being processed concurrently.
Monitoring and Logging Complement Each Other
A production service should have both logging and monitoring. Monitoring provides a real-time statistical summary of the system state. It can alert you if a percentage of certain request types are failing, it is experiencing unusual traffic patterns, performance is degrading, or other anomalies occur. In some cases, this information alone will clue you to the cause of a problem. However, in most cases, a monitoring alert is simply a trigger for you to start an investigation. Monitoring shows the symptoms of problems. Logs provide details and state on individual transactions, so you can fully understand the cause of problems.
Optimal Logging的更多相关文章
- 读书摘要,Hackable Projects
完整读完Google的三篇谈Hackable Projects的文章,以及一篇从Test Pyramid看UnitTest的比重.一篇谈Optimal Logging的文章,感觉这5篇在测试.日志两个 ...
- Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
学习架构探险,从零开始写Java Web框架时,在学习到springAOP时遇到一个异常: "C:\Program Files\Java\jdk1.7.0_40\bin\java" ...
- Oracle补全日志(Supplemental logging)
Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...
- Java程序日志:java.util.logging.Logger类
一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...
- python 学习笔记 -logging模块(日志)
模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...
- python logging colorlog
import logging LOG_LEVEL = logging.NOTSET LOGFORMAT = "[%(log_color)s%(levelname)s] [%(log_colo ...
- [转]ASP.NET Core 开发-Logging 使用NLog 写日志文件
本文转自:http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 . ...
- python 之 logging
#coding=utf-8 import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename ...
- Python Logging模块的简单使用
前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...
随机推荐
- LoadRunner调用Java程序—性能测试
为了充分利用LoadRunner的场景控制和分析器,帮助我们更好地控制脚本加载过程,从而展现更直观有效的场景分析图表.本次将重点讨论LoadRunner如何调用Java测试代码,完成压力测试. 通常我 ...
- oracle创建库和表
SQL> create user midamtemp identified by ty1234 default tablespace midamtemp; User created. --分配用 ...
- Trie树模板~~~
* + ; ; // 字母表为全体小写字母的Trie struct Trie { int ch[maxnode][sigma_size]; int val[maxnode]; int sz; // 结 ...
- Add And Reset a Federation Server to a Federation Server Farm adfs ad
Applies To: Active Directory Federation Services (AD FS) 2.0 After you install the Active Directory ...
- stream转byte数组几种方式
第一种,写法最简单的.使用原生IO,一个字节一个字节读: //一个字符一个字符读,太慢 int i; while((i=in.read()) != -1){ i = in.read(); arr[j+ ...
- 问题-Delphi记忆工程打开的单元(XE2设置项)
问题情况:每次在delphi中打开了N个单元的窗口,关闭delphi后,第二天还得一个一个打开单元窗口.问题原因:这是因为delphi的记忆功能未打开.问题处理:Tools->Options.. ...
- [置顶] 使用U盘安装ubuntu系统
使用U盘安装ubuntu系统 在网上找了很多教程,都不起效,提示:“从光盘上读取数据出错”. 总结出了几个关键点. 首先,版本,Ubuntu 12.04 Server,一般的U盘安装都会报:“从光盘上 ...
- [一]java环境变量的配置
1.JAVA_HOME(新建):D:\jdk1.6 2.classpath(新建): .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar; 3.path(新增):% ...
- [四]JFreeChart实践三之饼图
饼图pie 原理总结 1.准备好要显示的数据放入dataset 2.调用ChartFactory将dataset作为参数传递进去,生成chart 3.掉Servlet工具类将chart作为参数传入生成 ...
- Zabbix lld发现磁盘监控
一.软件版本 操作系统:CentOS-6.5-x86_64 zabbix版本:3.0.3 二.脚本编写: 1.python版本: #!/usr/bin/env python import json i ...