Java进阶(五十二)利用LOG4J生成服务日志

前言

由于论文写作需求,需要进行流程挖掘。前提是需要有真实的事件日志数据。真实的事件日志数据可以用来发现、监控和提升业务流程。

为了获得真实的事件日志数据,决定采用Log4J日志生成工具。首先,对工具有个大致的了解:日志是应用软件中不可缺少的部分,Apache的开源项目Log4j是一个功能强大的日志组件,提供方便的日志记录。

Log4j下载

在apache网站:http://logging.apache.org/log4j/1.2/download.html

可以免费下载到Log4j最新版本的软件包。

Log4j使用

Log4j的包下载完成后,解压,将其中打包好的的log4j-1.x.x.jar导入你的工程lib中。

Log4j之所以受欢迎的原因之一是它的灵活性。Log4j提供了灵活的配置方法,默认是调用BasicConfigurator.configure()来进行配置,但如果只是简单的调用BasicConfigurator.configure()来进行配置工作,那么所有的配置都是固定的,不方便以后修改配置。另一种是动态配置,Log4j提供了PropertyConfigurator.configure(……)来动态配置,参数可以是一个properties文件所在路径的String对象,可以是一个properties文件所在路径的URL对象,也可以是一个properties对象。如果要用XML文件来配置信息,则可用类型的DOMConfigurator()函数来从一个XML文件中加载配置信息。这种方式更方便修改配置。

package http;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
public class Log4jDemo {
     static Logger log = Logger.getLogger(Log4jDemo.class.getClass());
     public static void main(String[] args) {
         BasicConfigurator.configure();//默认配置
         PropertyConfigurator.configure("c:/log4j.properties");
//动态配置,参数可以是一个properties文件所在路径的String对象
//可以是一个properties文件所在路径的URL对象,也可以是一个properties对象
//PropertyConfigurator.configure()的参数还可以是XML、Properties对象
         DOMConfigurator.configure("c:/log4j.xml");//XML配置文件
         //下面就可使用log4j
         log.info("info");
         log.debug("debug");
         log.error("error");
         log.warn("warn");
     }
 }  

J2EE应用log4j

在J2EE应用使用Log4j,必须先在启动服务时加载Log4j的配置文件进行初始化,可以在web.xml中进行。

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;   

public class J2eeLog4jDemo extends HttpServlet {
    public void destroy() {
        super.destroy();
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    public void init() throws ServletException {
        //通过web.xml来动态取得配置文件
        String prefix = getServletContext().getRealPath("/");
        String file = getInitParameter("log4j");
        //如果没有给出相应的配置文件,则不进行初始化
        if(file != null)
        {
            PropertyConfigurator.configure(prefix+file);
        }
    }
}

Web.xml 代码

<servlet>
    <servlet-name>j2eelog4jdemo<servlet-name>
    <servlet-class>J2eeLog4jDemo<servlet-class>
    <init-param>
    <param-name>log4j<param-name>
    <param-value>log4j.properties<param-value>
    </init-param>
    <load-on-startup>1<load-on-startup> //设为1时Web容器启动即进行加载
</servlet> 

Log4j配置内容

Log4j配置内容主要是依据配置文件log4j.properties:

#指定根Logger,及日志输出级别

#大于等于该级别的日志将被输出( DEBUG < INFO < WARN < ERROR < FATAL ),设为OFF可以关闭日志,指定日志信息输出到哪个地方。可以同时指定多个输出目的地。

log4j.rootLogger=DEBUG, A1,A2

#指定log输出目的,这里设为输出日志到指定目录的文件my.log中

log4j.appender.A1=org.apache.log4j.FileAppender

log4j.appender.A1.File=\\logs\\my.log   #当前根目录下

#指定日志信息的格式

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%r %d{yyyy-MM-dd HH:mm:ss} %c %p -%m%n

#把A2输出到控制台

log4j.appender.A2=org.apache.log4j.ConsoleAppender

log4j.appender.A2.layout=org.apache.log4j.SimpleLayout

#还可以单独指定输出某个包的日志级别

#log4j.logger.com.study.HelloLog4j=INFO

1、配置根Logger

其语法为: log4j.rootLogger = [ level ] , appenderName, appenderName2

level:日志的级别,指定这条日志信息的重要性。分为ALL < DEBUG < INFO < WARN < ERROR < FATAL。一般常用的为 DEBUG , INFO ,WARN ,ERROR四种,分别对应Logger类的四种方法

debug(Object message ) ;

info(Object message ) ;

warn(Object message ) ;

error(Object message ) ;

如果设置级别为INFO,则优先级大于等于INFO级别(如:INFO、WARN、ERROR)的日志信息将可以被输出,小于该级别的如:DEBUG将不会被输出

appenderName :就是指定日志信息输出目的地,比如(打印到控制台,输出到文件等)。同一条日志信息可以配置多个输出目的地。

2、配置log输出目的地

Log4j提供以下几种:

org.apache.log4j.ConsoleAppender(控制台)

org.apache.log4j.FileAppender(文件)

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)

org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

3、log信息的格式

org.apache.log4j.HTMLLayout(HTML表格形式)

org.apache.log4j.SimpleLayout(简单格式的日志,只包括日志信息的级别和指定的信息字符串 ,如:DEBUG - Hello)

org.apache.log4j.TTCCLayout(日志的格式包括日志产生的时间、线程、类别等等信息)

org.apache.log4j.PatternLayout(灵活地自定义日志格式)

当使用org.apache.log4j.PatternLayout来自定义信息格式时,可以使用

log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p -%m%n 来格式化信息

%c    输出所属类的全名,可写为 %c{Num} ,Num类名输出的范围  如:"com.sun.aaa.classB", %C{2}将使日志输出输出范围为:aaa.classB

%d    输出日志时间其格式为 可指定格式 如 %d{HH:mm:ss}等

%l    输出日志事件发生位置,包括类目名、发生线程,在代码中的行数

%n    换行符

%m    输出代码指定信息,如info(“message”),输出message

%p    输出日志的优先级,即 FATAL ,ERROR 等

%r    输出从启动到显示该条日志信息所耗费的时间(毫秒数)

%t    输出产生该日志事件的线程名

更详细参数信息可参看类org.apache.log4j.PatternLayout的API doc文档

后知后觉

经过查看,才发现原来项目中已经使用了log4j,自己需要给其再加上时间戳。不过这些日志还得经过后期的处理,因为现在的信息太琐碎了。

以下为某一交易的日志数据:

[21:20:52][weiming.lmapp.servlet.DoUpdate] pkgtype=json

[21:20:52][weiming.lmapp.servlet.DoUpdate] content-length=106

[21:20:52][weiming.lmapp.servlet.RequestMessage] receiver:{"billtype":"1236","version":"1.0","fore_time":"2015-12-09 21:20:52","uid":"18853883588","tx_code":"9010"}

[21:20:52][weiming.lmapp.trans.Transaction]

------------Order_Query_9010 debug info-------------

请求数据包信息:{"billtype":"1236","version":"1.0","fore_time":"2015-12-09 21:20:52","uid":"18853883588","tx_code":"9010"}

[21:20:52][weiming.lmapp.trans.Transaction] stat:[1]

[21:20:52][weiming.lmapp.trans.Transaction] stat:[2]

[21:20:52][weiming.lmapp.trans.Transaction] stat:[3]

[21:20:52][weiming.lmapp.trans.Transaction] stat:[6]

[21:20:52][weiming.lmapp.trans.Transaction] 查询条件:[buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' )ORDER BY tx_time DESC]

[21:20:52][weiming.database.lmapp.MyDatabase] sqlstr=select billid,tx_time,buy_uid,merch_uid,msg,old_amt,amt,receiver,tel,buy_addr,stat,pay_type,pl_stat from lm_bill where buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' )ORDER BY tx_time DESC limit 0,1000

[21:20:52][weiming.lmapp.trans.Transaction] count:[1]

[21:20:52][weiming.database.lmapp.MyDatabase]sqlstr=select billid,cnt,medid,medname,medcnt,medprice,medamt,cfid from lm_bill_dtl where billid='LM2015120935888906' limit 0,1000

[21:20:52][weiming.lmapp.servlet.DoUpdate] Transaction 9010 success

[21:20:52][weiming.lmapp.servlet.RequestMessage] OUTSTR:

{"cnt":1,"data":[{"med_amt":8,"amt":8,"med_cnt":1,"tx_time":"2015-12-09 21:20:49","medname":"感冒灵颗粒","medid":"TZ20055267","stat":"1","billid":"LM2015120935888906"}],"result":"0000","errtext":""}

经过观察,发现以上日志数据并不完全满足自己的需求,需做进一步的改进。改进后产生的日志信息如下:

[15/12/09 21:50:36:332][weiming.lmapp.servlet.DoUpdate] pkgtype=json

[15/12/09 21:50:36:333][weiming.lmapp.servlet.DoUpdate] content-length=107

[15/12/09 21:50:36:333][weiming.lmapp.servlet.RequestMessage] receiver:{"billtype":"12369","version":"1.0","fore_time":"2015-12-09 21:50:36","uid":"18853883588","tx_code":"9010"}

[15/12/09 21:50:36:333][weiming.lmapp.trans.Transaction]

------------Order_Query_9010 debug info-------------

请求数据包信息:{"billtype":"12369","version":"1.0","fore_time":"2015-12-09 21:50:36","uid":"18853883588","tx_code":"9010"}

[15/12/09 21:50:36:333][weiming.lmapp.trans.Transaction] stat:[1]

[15/12/09 21:50:36:334][weiming.lmapp.trans.Transaction] stat:[2]

[15/12/09 21:50:36:334][weiming.lmapp.trans.Transaction] stat:[3]

[15/12/09 21:50:36:334][weiming.lmapp.trans.Transaction] stat:[6]

[15/12/09 21:50:36:334][weiming.lmapp.trans.Transaction] stat:[9]

[15/12/09 21:50:36:334][weiming.lmapp.trans.Transaction] 查询条件:[buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' OR stat='9' )ORDER BY tx_time DESC]

[15/12/09 21:50:36:334][weiming.database.lmapp.MyDatabase] sqlstr=select billid,tx_time,buy_uid,merch_uid,msg,old_amt,amt,receiver,tel,buy_addr,stat,pay_type,pl_stat from lm_bill where buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' OR stat='9' )ORDER BY tx_time DESC limit 0,1000

[15/12/09 21:50:36:335][weiming.lmapp.trans.Transaction] count:[1]

[15/12/09 21:50:36:336][weiming.database.lmapp.MyDatabase] sqlstr=select billid,cnt,medid,medname,medcnt,medprice,medamt,cfid from lm_bill_dtl where billid='LM2015120935888906' limit 0,1000

[15/12/09 21:50:36:337][weiming.lmapp.servlet.DoUpdate] Transaction 9010 success

[15/12/09 21:50:36:338][weiming.lmapp.servlet.RequestMessage] OUTSTR:

{"cnt":1,"data":[{"med_amt":8,"amt":8,"med_cnt":1,"tx_time":"2015-12-09 21:20:49","medname":"感冒灵颗粒","medid":"TZ20055267","stat":"9","billid":"LM2015120935888906"}],"result":"0000","errtext":""}

通过观察可以发现,以上日志主要包含的信息有:服务请求者、服务时间段、服务内容、服务结果

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

学术需要,现在自己需要实现按日期生成日志文档,log4j配置如下:

log4j.appender.appender2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.appender2.DatePattern=yyyy-MM-dd'.log'
log4j.appender.appender2.layout=org.apache.log4j.PatternLayout
log4j.appender.appender2.layout.ConversionPattern=[%d{yy/MM/dd 	HH:mm:ss:SSS}][%c] %m%n
log4j.appender.appender2.File=e\:\\MyEclipse10\\logs\\log_

当天生成的日志,保存在项目的根路径下的","tx_code":""}

[15/12/09 22:02:21:532][weiming.lmapp.trans.Transaction]

------------Order_Query_9010 debug info-----------

请求数据包信息:

{"billtype":"1236","version":"1.0","fore_time":"2015-12-09 22:02:22","uid":"18853883588","tx_code":"9010"}

[15/12/09 22:02:21:547][weiming.lmapp.trans.Transaction] stat:[1]

[15/12/09 22:02:21:547][weiming.lmapp.trans.Transaction] stat:[2]

[15/12/09 22:02:21:547][weiming.lmapp.trans.Transaction] stat:[3]

[15/12/09 22:02:21:547][weiming.lmapp.trans.Transaction] stat:[6]

[15/12/09 22:02:21:547][weiming.lmapp.trans.Transaction] 查询条件:

[buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' )ORDER BY tx_time DESC]

[15/12/09 22:02:21:547][weiming.database.lmapp.MyDatabase] sqlstr=

selectbillid,tx_time,buy_uid,merch_uid,msg,old_amt,amt,receiver,tel,buy_addr,stat,pay_type,pl_stat from lm_bill where buy_uid='U18853883588' AND ( stat='1' OR stat='2' OR stat='3' OR stat='6' )ORDER BY tx_time DESC limit 0,1000

[15/12/09 22:02:21:595][weiming.lmapp.trans.Transaction] count:[0]

[15/12/09 22:02:21:595][weiming.lmapp.trans.Transaction]

[15/12/0922:02:21:595][weiming.lmapp.servlet.DoUpdate]Transaction 9010 error

[15/12/09 22:02:21:595][weiming.lmapp.servlet.RequestMessage] OUTSTR:

{"cnt":0,"result":"9999","errtext":"无订单信息"}

获取到了数据源信息,自己就需要做进一步的处理了。

Java进阶(五十二)利用LOG4J生成服务日志的更多相关文章

  1. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  2. “全栈2019”Java第五十二章:继承与初始化详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. Java性能调优:利用JFR生成性能日志

    Java性能调优作为大型分布式系统提供高性能服务的必修课,其重要性不言而喻. 好的分析工具能起到事半功倍的效果,利用分析利器JMC.JFR,可以实现性能问题的准确定位. 本文主要阐述如何利用JFR生成 ...

  4. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  5. 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条

    http://blog.csdn.net/terryzero/article/details/3797782 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条 标签: swing编程 ...

  6. Java进阶(三十五)java int与integer的区别

    Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...

  7. 《手把手教你》系列技巧篇(五十二)-java+ selenium自动化测试-处理面包屑(详细教程)

    1.简介 面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了 ...

  8. 201871010106-丁宣元 《面向对象程序设计(java)》第十二周学习总结

    201871010106-丁宣元 <面向对象程序设计(java)>第十二周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://home.cnblogs.com/u/nw ...

  9. Gradle 1.12用户指南翻译——第五十二章. Maven 插件

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上 ...

随机推荐

  1. jdbc批量插入

    分享牛,分享牛原创.有这样一个需求,文本文件中的数据批量的插入mysql,怎么用jdbc方式批量插入呢? jdbc默认提供了批量插入的方法,可能用一次就忘记了,这里做笔记记录一下jdbc批量插入吧. ...

  2. zookeeper分布式锁

    摘要:分享牛原创,zookeeper使用,zookeeper锁在实际项目开发中还是很常用的,在这里我们介绍一下zookeeper分布式锁的使用,以及我们如何zookeeper分布式锁的原理.zooke ...

  3. Most Common Solutions to FRM-41839 and .tmp Files Not Being Deleted

    In this Document   Symptoms   Changes   Cause   Solution   References APPLIES TO: Oracle Application ...

  4. PHP 针对多用户 实现头像更换

    成品图 思路 登陆页面 表单制作 验证码制作 JavaScript刷新验证码 验证页面 验证逻辑 页面跳转 header函数 Meta标签 JavaScript 上传页面 个人主页 上传核心 最终结果 ...

  5. SQLite 附加数据库(http://www.w3cschool.cc/sqlite/sqlite-attach-database.html)

    SQLite 附加数据库 假设这样一种情况,当在同一时间有多个数据库可用,您想使用其中的任何一个.SQLite 的 ATTACH DTABASE 语句是用来选择一个特定的数据库,使用该命令后,所有的 ...

  6. Java 单元测试 JUnit4 快速入门

    JUnit最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class CardServiceTest {     /**      * 最佳 ...

  7. [csdn markdown]使用摘记一源代码高亮及图片上传和链接

    本文主要内容是体验csdn markdown的代码块高亮显示和图片链接及上传. 图片上传 上边这是标题行,只需要使用一个#就可以表示,几个表示是几级标题 图片上传 本地图片上传控件 本地图片上传方式 ...

  8. 6.1、Android Studio的Android Monitor概览

    Android Monitor帮助你监测你的应用的性能,以帮助你合理的进行优化,调试,提升.如下功能: 1. Log消息,系统定义的或者开发者定义的. 2. 内存,CPU和GPU使用情况. 3. 网络 ...

  9. 关于MySQL-python-1.2.3.tar.gz安装失败的解决方案

    关于MySQL-python-1.2.3.tar.gz安装失败的解决方案 RHEL6.4升级到python2.7.9,然后安装 MySQL-python-1.2.3.tar.gz, 报错.解决错误之后 ...

  10. How to Find the Self Service Related File Location and Versions

     How to Find the Self Service Related File Location and Versions (文档 ID 781385.1) In this Document ...