真正做项目,才发觉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的这点小事的更多相关文章

  1. 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" ...

  2. Oracle补全日志(Supplemental logging)

    Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...

  3. 谈谈React那些小事

    前言 说起React,那也是近一年多时间火起来的前端框架,其在Facebook的影响力和大力推广下,已然成为目前前端界的中流砥柱.在如今的前端框架界,React.Vue.Angular三分天下的时代已 ...

  4. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  5. python 学习笔记 -logging模块(日志)

    模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...

  6. python logging colorlog

    import logging LOG_LEVEL = logging.NOTSET LOGFORMAT = "[%(log_color)s%(levelname)s] [%(log_colo ...

  7. [转]ASP.NET Core 开发-Logging 使用NLog 写日志文件

    本文转自:http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 . ...

  8. python 之 logging

    #coding=utf-8 import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename ...

  9. Python Logging模块的简单使用

    前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...

随机推荐

  1. Android简单加密保护自有图片资源

    现在大部分android应用的图片资源,被反编译后就可以直接拿来用,如果不想让自己的图片资源直接被反编译后使用,首先想到的应该是把图片加密.这里笔者抛砖引玉,草草写了一个对图片进行简单加密的方法,希望 ...

  2. Web API与国际化

    软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化习俗,在创建不同语言版本时,不需要重新设计源程序代码的软件工程方法.这在很多成熟的软件开发平台中非常常见.对于.net开发 ...

  3. Java Se :Map 系列

    之前对Java Se中的线性表作了简单的说明.这一篇就来看看Map. Map系列的类,并不是说所有的类都继承了Map接口,而是说他们的元素都是以<Key, Value>形式设计的. Dic ...

  4. Javascript之旅——第二站:对象和数组

    一觉睡到中午,本来准备起来洗洗继续睡,不过想想没辙,还得继续这个系列,走过变量的第一站,第二站我们再来看看对象和数组. 一:对象   说起对象,我们不自然就想起了面向对象中自封装的一个类,同样JS中也 ...

  5. Linux下Nagios的安装与配置[转]

    一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...

  6. 10个开源的PHP网站内容管理系统

    1. DEDE -这是一款国内开源的cms,作者是一个个人,能做出如此功能的cms,是相当不错的.2007版功能十分强大,希望能改善之前数据量一大,更新静态页就很慢的缺点.因为开源,有较多的玩家和拥护 ...

  7. iOS解决隐藏导航栏后,打开照片选择器后导航栏不显示的问题以及更换导航栏背景色

    问题描述: 遇到一种情况,在一个控制器上(隐藏了导航栏),打开照片选择器 UIImagePickerController后,照片选择器头部一片空白,且上滑相册时,信息会有错乱效果. 原因分析: 通过查 ...

  8. file

    用来测试文件类型 $file [] filename -b列出辨识结果时,但不显示文件名称 -L如果文件是符号链接,那么直接解读其指向的文件 -z:如果文件是压缩文件,尝试去解读压缩文件的内容 $fi ...

  9. java 自动装箱自动拆箱

    1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...

  10. 浅谈 Linux 内核无线子系统

    浅谈 Linux 内核无线子系统 本文目录 1. 全局概览 2. 模块间接口 3. 数据路径与管理路径 4. 数据包是如何被发送? 5. 谈谈管理路径 6. 数据包又是如何被接收? 7. 总结一下 L ...