Logging的这点小事
真正做项目,才发觉Logging的好处和学问。自己胡搞的时候,常常使用System.out.println作为输出。
但实际的项目,尤其是library比较多的时候,好好配置好Logging,才能在后面的工作以及追查结果时,事半功倍。否则,很有可能无法获取所有的log以致无法追查问题发生的原因。
首先介绍的,是最传统的log4j。log4j的使用相当简单。例子如下:
// get a logger instance named "com.foo"
Logger logger = Logger.getLogger("com.foo"); // Now set its level. Normally you do not need to set the
// level of a logger programmatically. This is usually done
// in configuration files.
logger.setLevel(Level.INFO); Logger barlogger = Logger.getLogger("com.foo.Bar"); // This request is enabled, because WARN >= INFO.
logger.warn("Low fuel level."); // This request is disabled, because DEBUG < INFO.
logger.debug("Starting search for nearest gas station."); // The logger instance barlogger, named "com.foo.Bar",
// will inherit its level from the logger named
// "com.foo" Thus, the following request is enabled
// because INFO >= INFO.
barlogger.info("Located nearest gas station."); // This request is disabled, because DEBUG < INFO.
barlogger.debug("Exiting gas station search");
值得注意的,是log4j的日志优先级:TRACE<DEBUG<INFO<WARN<ERROR<FATAL;以及,日志的配置文件和方法:
#1. Logger: Logger分根Logger(Root Logger)和其它类Logger;主要是定义日志优先级和是否Additivity:
<!-- root logging -->
<root>
<priority value ="INFO" />
<appender-ref ref="console"/>
<appender-ref ref="common"/>
</root> <!-- specific logger for abc -->
<logger name="com.test.abc" additivity="false">
<level value="INFO"/>
<appender-ref ref="AAppender" />
</logger>
log4j.additivity指定特定包下的类的日志信息是否输出到rootLogger中,true表示输出,false表示不输出。
#2. Appender: Appender是真正进行日志记录的类;通常的做法是通过配置不同的Appender分发给不同的Logger,达到多层级日志的目的:
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyMMdd HH:mm:ss} [%-5p] %m --By %t : %l%n"/>
</layout>
</appender> <!-- for common logging -->
<appender name="common" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="logs/common.log"/>
<param name="Threshold" value="DEBUG"/>
<param name="DatePattern" value="'.'yyyyMMdd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss} [%-5p] %m --By %t : %l%n"/>
</layout>
</appender> <!-- for journal logging-->
<appender name="AAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="logs/a.log"/>
<param name="Threshold" value="DEBUG"/>
<param name="DatePattern" value="'.'yyyyMMdd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss} [%-5p] %m --By %t\n"/>
</layout>
</appender>
Appender的配置非常丰富,也有不少定义好的Appender可以选择(ConsoleAppender, DailyRollingFileAppender),这里不展开,详细的配置可以参考官网。
#3. Category:log4j.category是对日志类别的补充说明,可以指定特定包下的日志使用category指定的日志级别和appender。例如:
<category name="org.springframework.jdbc.core.namedparam">
<priority value="ERROR"/>
</category>
这样,某个特定的类,例如spring下的这个包的类,输出的日志级别提高到了ERROR
由于历史原因,不同的库使用的logging framework并不一样,例如大名鼎鼎的Spring,使用的其实是commons-logging,还有Java本身的logging framework。如果不统一起来管理,那么Spring发生的错误,只会通过commons-logging输出到console,而不会被log4j记录下来。所以,不同的日志系统,需要统一起来管理,统一由log4j输出。这样,就需要SLF4J.
SLF4J本质上,就是做刚刚所说的统一管理Logging的工作,真正日志记录的工作,交给log4j。Spring用commons-logging对吧,没问题,SLF4J有一个包是jcl-over-slf4j,把commons-logging的日志输出到SLF4J;又例如LMAX Disruptor是用java.util.logging,也没问题,SLF4J有一个包是jul-to-slf4j,把java的logging输出到SLF4J。那么SLF4J输出到哪里了?通过slf4j-log4j12这个包,输出到log4j这里,统一在输出到各自的appender那里。
这样,可以保证所有的日志,都可以被记录下来。
需要注意的是,使用jul-to-slf4j时,需要代码上开启桥接java.util.logging到slf4j:
// Enable logging of Disruptor point to slf4j
LogManager.getLogManager().reset();
SLF4JBridgeHandler.install();
本文完
Logging的这点小事的更多相关文章
- 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 ...
- 谈谈React那些小事
前言 说起React,那也是近一年多时间火起来的前端框架,其在Facebook的影响力和大力推广下,已然成为目前前端界的中流砥柱.在如今的前端框架界,React.Vue.Angular三分天下的时代已 ...
- 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 ...
随机推荐
- PlateSpin 完全复制由于LVM没有可用空闲空间导致失败
使用PlateSpin复制居然会由于LVM的卷组VG没有空闲可用的空间(available free space in the LVM volume group)创建快照而导致失败,特此记录一下:免得 ...
- 深入解析Windows操作系统笔记——CH1概念和术语
1.概念和工具 本章主要介绍Windows操作系统的关键概念和术语 1.概念和工具 1.1操作系统版本 1.2基础概念和术语 1.2.1Windows API 1.2.2 服务.函数和例程 1.2.3 ...
- Bug #19528825 "UNABLE TO PURGE A RECORD"
概述: 在生产环境中,当开启insert buffer时(参数innodb_change_buffering=all),部分实例偶尔会出现“UNABLE TO PURGE A RECORD”错误.这个 ...
- AS与.net的交互——加载web上的xml
最近搞了个私活,需要用as去加载一个网站的xml,不过本人as也不咋滴,就去看看怎么玩,看完之后也蛮简单的. 由于业务上比较复杂,就随便说个小例子吧. 很多时候,为了页面区域更加灵活,生动,有吸引力, ...
- 按要求编写Java应用程序。 (1)建立一个名叫Cat的类: 属性:姓名、毛色、年龄 行为:显示姓名、喊叫 (2)编写主类: 创建一个对象猫,姓名为“妮妮”,毛色为“灰色”,年龄为2岁,在屏幕上输 出该对象的毛色和年龄,让该对象调用显示姓名和喊叫两个方法。
package zuoye; public class Cat { String name="妮妮"; String color="灰色"; int age=1 ...
- 说一下output子句
Output子句日常灰常有用,而且用的地方也挺多,但是确好多时候被我们忽视,今天我就也简单扫盲一下这个语句的用法. Output子句 返回受 INSERT.UPDATE.DELETE 或 MERGE ...
- DataTable操作
一 复制DataTable中符合条件的DataRow到新的DataTable中 One: DataTable TableTemp = new DataTable();//临时table DataTab ...
- Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表
Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表 一个个人觉得比较简单小巧的软件. 下面就如何编写如何发布打包来介绍一下吧! 先下载mysql的库文件链接:http://files. ...
- STM32学习笔记——USART串口
转载自:http://www.cnblogs.com/microxiami/p/3752715.html 一.USART简介 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异 ...
- Scala编程第二课
函数式编程 函数式编程,结构化编程,OO编程都是编程的方法论. 函数式编程主要思想是把运算过程尽量写成一系列嵌套的函数调用. 特点如下: 1.函数可以像其他数据类型一样使用 可以可以赋值给其他变量,可 ...