【User Story2.0】
1.使用应用程序是客户,如果程序出了问题,一般客户能提供精确步骤就阿弥陀佛了。
如果我们仅仅使用调试器断点机制,该问题没有重现,会让我们以为已经解决了,但其实问题藏的深,可能是多线程有关呢(因为断点让执行速度变慢了)。
所以【成功地调试程序、监控和错误报告地关键是【日志】】
2.K&R的K和Rob Pike总结 一、 认真思考添加输出语句+在关键位置代码自检 更快于 仅仅通过调试器获得栈或者就1个变量值(复杂数据结构和控制流细节会丢失)
.二、浏览可疑位置【输出】 更省时于 单击跳过语句查看
.三、输出可以保留在程序中 更好于 等下要手动去掉调试。
总结:我们无法用调试器监控 客户在生产环境下的应用程序,所以计划在不使用调试器解决问题的思路是合乎情理的。
话外音:System.err System.out 缺少粒度 会妨碍应用程序的性能 ,所以我们需要的是可以配置显示多或少日志信息...
【在日志记录内容】
1.当系统崩溃会阻止日志机制工作,因此JVM内建了工具,Oracle和OpenJDK 的JVM添加-XX:+HeapDumpOnOutOfMemoryError在JVM内存益处时生成堆转储。
2.用日志记录关于错误【所有信息】(类型、消息、栈跟踪以及最后一次程序在干嘛),对用户不能暴露可能危害系统的信息(文件路径、SQL查询)
3.虽然【警告】可以引起人注意,表示应用程序潜在的问题。
4.【重要】事件,帮助我们了解系统是否正常,如实体创建、组件启动、用户登录成功、任务执行成功。
5.最困难的调试场景中,需要打印出进入方法或者退出方法时间,以及每个方法的参数值和返回值。高负载应用程序中,执行循环要打印出迭代数据。
【日志写入方式】
1.Console
2.XML日志比较臃肿、JSON日志可读性稍差一点、在Linux中 syslog是一种所有进程可以写入的设备。
滚动文件可以应用在上述的模式,周期性(时间或文件大小)改变日志文件,比如Tomcat每天都会创建新的日志文件。
3.套接字 专门日志服务器
4.SMTP和SMS 被用于通知系统管理员要立即解决的问题。
5.数据库 高效且事务安全、易于查询和过滤、审核数据(法律)也不怕,缺点是数据写入索引表引起网络栈开销,写入速度慢,限制数据库大小(尝试关闭代价是更耗时不利于过滤日志)
推荐NoSQL,存储数百GB甚至TB仍然保持良好的性能。比如MongoDB以BSON二进制存储JSON,进一步压缩了数据,但牺牲的是读的性能所以过滤非常慢。
(缺点MongoDB不是ACID兼容的,需要我们构造正确的文档结构)
【日志的级别和分类】
java.utl.logging.Level定义的常量
Apache HTTPD定义的日志界别 emerg、alert、crit、error、warn、notice、info、debug、trace1~trace8
【选择日志框架】
场景:现有数千个类都使用了日志的企业级应用程序,要从syslog输出改成数据库日志输出,潜在问题是日志API被耦合在具体实现上,如果不修改所有日志代码就无法替换。
解决:编写简单的日志API隐藏底层框架,然后在更换框架时只需要修改API几个类,其他程序可以继续使用API记录日志。
java.util.logging已经帮我们将日志API和实现分离,在收到请求时,java.utl.logging.LogManager类负责创建和返回Logger实例,我们可以扩展LogManager。
标准实现具有可以写入文件、流、套接字、console、内存处理器,缺点是不适合Web应用程序,因为它从系统属性加载配置而不是Classpath。
=>【选择框架的原因】不能从Classpath加载配置的话,部署到同一个容器的两个web应用程序不可以有不同日志配置,这样就不好移植。
=>【性能】无论开发应用程序哪个部分,向文件、Socket、数据库、电子邮件,这些任务会耗费时间在阻塞上等待输入输出完成,又是靠操作系统控制进而无法通过软件加速这一过程。
【典型的框架】CommonsLogging和SLF4J 通常Scope=Compile,而它们的实现Scope=runtime,这样避免了应用程序直接使用底层实现。
SLF4J的LoggerFactory.getLogger方法将返回Logger...
【Log4j 2】最重要的指标 关闭日志性能。
和Logback相比,性能大致相同,Log4j 2擅长在于日志过滤器。
直接使用Log4j 2 API而不用SLF4J的原因,因为前者更完整,特性丰富。