处理Apache日志的Bash脚本

 log  处理Apache日志的Bash脚本已关闭评论
12月 142016
 

来自阮一峰的博客,学习了, 转自:http://www.ruanyifeng.com/blog/2012/01/a_bash_script_of_apache_log_analysis.html

以往,我用的是AWStats日志分析软件。它可以生成很详细的报表,但是不太容易定制,得不到某些想要的信息。所以,我就决定自己写一个Bash脚本,统计服务器的日志,顺便温习一下脚本知识。

事实证明,这件事比我预想的难。虽然最终脚本只有20多行,但花了我整整一天,反复查看手册,确认用法和合适的参数。下面就是我的日志分析脚本,虽然它还不是通用的,但是我相信里面用到的命令,足以满足一般的日志分析需求,同时也是很好的学习Bash的实例。如果下面的每一个命令你都知道,我觉得可以堪称熟练使用Bash了。

一、操作环境

在介绍脚本之前,先讲一下我的服务器环境。

我的网络服务器软件是Apache,它会对每一个http请求留下记录,就像下面这一条:

203.218.148.99 – – [01/Feb/2011:00:02:09 +0800] “GET /blog/2009/11/an_autobiography_of_yang_xianyi.html HTTP/1.1” 200 84058 “http://www.ruanyifeng.com/blog/2009/11/freenomics.html” “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13”

它的意思是2011年2月1日,IP地址为203.218.148.99的访问者,向服务器请求访问网址/blog/2009/11/an_autobiography_of_yang_xianyi.html。

当天所有的访问记录,组成一个日志。过去一年,一共生成了365个日志文件。它们存放在12个目录中,每一个目录表示一个月(2011-01、2011-02、……2011-12),里面的日志文件依次为www-01.log、www-02.log、……www-31.log(假定该月有31天)。

在不压缩的情况下,365个日志文件加起来,要占掉10GB空间。我的目标就是分析这10GB日志,最后得到一个如下形式的访问量排名:

访问量 网址1
访问量 网址2
访问量 网址3
…… ……

二、为什么要用Bash

很多计算机语言,都可以用来完成这个任务。但是,如果只是简单的日志分析,我觉得Bash脚本是最合适的工具。

主要原因有两个:一是”开发快”,Bash脚本是各种Linux命令的组合,只要知道这些命令怎么用,就可以写脚本,基本上不用学习新的语法,而且它不用编译,直接运行,可以边写边试,对开发非常友好。二是”功能强”,Bash脚本的设计目的,就是为了处理输入和输出,尤其是单行的文本,所以非常合适处理日志文件,各种现成的参数加上管道机制,威力无穷。

前面已经说过,最终的脚本我只用了20多行,处理10GB的日志,20秒左右就得到了结果。考虑到排序的巨大计算量,这样的结果非常令人满意,充分证明了Bash的威力。

三、总体思路

我的总体处理思路是这样的:

第一步,处理单个日志。统计每一天各篇文章的访问量。

第二步,生成月度排名。将每一天的统计结果汇总,得到月度访问量。

第三步,生成年度排名。将12个月的统计结果汇总,进行年度访问量的排序。

四、处理单个日志

以2011年1月1日的日志为例,它在目录2011-01之中,文件名是www-01.log,里面有10万条如下格式的记录:

203.218.148.99 – – [01/Feb/2011:00:02:09 +0800] “GET /blog/2009/11/an_autobiography_of_yang_xianyi.html HTTP/1.1” 200 84058 “http://www.ruanyifeng.com/blog/2009/11/freenomics.html” “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13”

处理这个日志,我只用了一行代码:

awk ‘$9 == 200 {print $7}’ www-01.log | grep -i ‘^/blog/2011/.*\.html$’ | sort | uniq -c | sed ‘s/^ *//g’ > www-01.log.result

它用管道连接了5个命令,每一个都很简单,我们依次来看:

(1) awk ‘$9 == 200 {print $7}’ www-01.log

awk命令默认用空格,将每一行文本分割成若干个字段。仔细数一下,我们需要的只是第7个字段,即http请求的网址,{print $7}表示将第7个字段输出,结果就是:

/blog/2009/11/an_autobiography_of_yang_xianyi.html

考虑到我们只统计成功的请求,因此再加一个限制条件,服务器的状态代码必须是200(表示成功),写成”$9 == 200″,即第9个字段必须是200,否则不输出第7个字段。

更精细的统计,还应该区分网络蜘蛛和真实访问者,由于我想不出简单的分辨方法,这里只好忽略了。

(2)grep -i ‘^/blog/2011/.*\.html$’

在输出的所有记录的第7个字段之中,并不是每一条记录都需要统计的。根据我的文章的命名特点,它们的网址应该都以”/blog/2011/”开头,以”.html”结尾。所以,我用一个正则表达式”^/blog/2011/.*\.html$”,找出这些记录。参数i表示不区分大小写。

(3)sort

这时,所有需要统计的记录应该都列出来了,但是它们的次序是杂乱的。接着,使用sort命令,不过目的不是为了排序,而是把相同的网址排列在一起,为后面使用uniq命令创造条件。

(4)uniq -c

uniq的作用是过滤重复的记录,只保留一行。c参数的作用,是在每行的开头添加该记录的出现次数。处理之后的输出应该是这样的:

32 /blog/2011/01/guidelines_for_english_translations_in_public_places.html
32 /blog/2011/01/api_for_google_s_url_shortener.html
30 /blog/2011/01/brief_history_of_arm.html

它表示以上三篇文章,在1月1日的日志中,分别有32条、32条、30条的访问记录(即访问次数)。

(5)sed ‘s/^ *//g’ > www-01.log.result

上一步uniq命令添加的访问次数,是有前导空格的。也就是说,在上例的32、32、30之前有一连串空格,为了后续操作的方便,这里把前导空格删去。sed命令是一个处理行文本的编辑器,’s/^ *//g’是一个正则表达式(^和*之间有一个空格),表示将行首的连续空格替换为空(即删除)。接着,将排序结果重定向到文件www-01.result。单个日志分析就完成了。

五、月度汇总排名

经过上一步之后,1月份的31个日志文件,生成了31个对应的分析结果文件。为了汇总整个月的情况,必须把这31个结果文件合并。

(6)合并分析结果

for i in www-*.log.result 
do 
cat $i >> log.result
done

这是一个循环结构,把所有www-01.log.result形式的文件,都写进log.result文件。

然后,我用一行语句,计算月度排名。

sort -k2 log.result | uniq -f1 –all-repeated=separate |./log.awk |sort -rn > final.log.result

这行语句由3个命令和1个awk脚本组成:

(7)sort -k2 log.result

由于是31个文件汇总,log.result文件里面的记录是无序的,必须用sort命令,将相同网址的记录归类在一起。但是此时,访问次数是第一个字段,网址是第二个字段,因此参数k2表示根据第二个字段进行排序。

(8)uniq -f1 –all-repeated=separate

uniq的作用是过滤重复的记录,参数f1表示忽略第一个字段(访问次数),只考虑后面的字段(网址);参数表示all-repeated=separate,表示过滤掉所有只出现一次的记录,保留所有重复的记录,并且每一组之间用一个空行分隔。这一步完成以后,输出结果变成如下的形式:

617 /blog/2011/01/guidelines_for_english_translations_in_public_places.html
455 /blog/2011/01/guidelines_for_english_translations_in_public_places.html

223 /blog/2011/01/2010_my_blogging_summary.html
253 /blog/2011/01/2010_my_blogging_summary.html

相同网址都归在一组,组间用空行分割。为了简洁,上面的例子每一组只包含两条记录,实际上每一组都包含31条记录(分别代表当月每天的访问次数)。

(9)log.awk脚本

为了将31天的访问次数加总,我动了很多脑筋。最后发现,唯一的方法就是用awk命令,而且必须另写一个awk脚本。

#!/usr/bin/awk -f

BEGIN {
RS=”” #将多行记录的分隔符定为一个空行
}

{
sum=0 #定义一个表示总和的变量,初值为0
for(i=1;i<=NF;i++){ #遍历所有字段
if((i%2)!=0){ #判断是否为奇数字段
sum += $i #如果是的话,累加这些字段的值
}
}
print sum,$2 #输出总和,后面跟上对应的网址 
}

我已经对上面这个log.awk脚本加了详细注释。这里再说明几点:首先,默认情况下,awk将”\n”作为记录的分隔符,设置RS=””表示改为将空行作为分隔符,因此形成了一个多行记录;其次,NF是一个awk的内置变量,表示当前行的字段总数。由于输入文件之中,每一行都包含两个字段,第一个是访问数,第二个是网址,所以这里做一个条件判断,只要是奇数字段就累加,偶数字段则一律跳过。最后,每个记录输出一个累加值和网址,它们之间用空格分割。

(10)sort -rn > final.log.result

对awk脚本的处理结果进行排序,sort默认使用第一个字段,参数r表示逆序,从大往小排;参数n表示以数值形式排序,不以默认的字典形式排序,否则会出现10小于2的结果。排序结果重定向到final.log.result。至此,月度排名完成。

六、脚本文件

用一个脚本,包含上面两节所有的内容。

#!/bin/bash

if ls ./*.result &> /dev/null #判断当前目录中是否有后缀名为result的文件存在
then
rm *.result #如果有的话,删除这些文件
fi

touch log.result #创建一个空文件

for i in www-*.log #遍历当前目录中所有log文件
do 
echo $i … #输出一行字,表示开始处理当前文件
awk ‘$9 == 200 {print $7}’ $i|grep -i ‘^/blog/2011/.*\.html$’|sort|uniq -c|sed ‘s/^ *//g’ > $i.result #生成当前日志的处理结果
cat $i.result >> log.result #将处理结果追加到log.result文件
echo $i.result finished #输出一行字,表示结束处理当前文件
done

echo final.log.result … #输出一行字,表示最终统计开始

sort -k2 log.result | uniq -f1 –all-repeated=separate |./log.awk |sort -rn > final.log.result #生成最终的结果文件final.log.result

echo final.log.result finished #输出一行字,表示最终统计结束

python的日志模块logging学习

 log, python  python的日志模块logging学习已关闭评论
12月 222015
 

1.简单的将日志打印到屏幕

 

import logging

logging.debug(‘This is debug message’)
logging.info(‘This is info message’)
logging.warning(‘This is warning message’)

 

屏幕上打印:
WARNING:root:This is warning message

默认情况下,logging将日志打印到屏幕,日志级别为WARNING;
日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别。

2.通过logging.basicConfig函数对日志的输出格式及方式做相关配置

import logging

logging.basicConfig(level=logging.DEBUG,
                format=‘%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s’,
                datefmt=‘%a, %d %b %Y %H:%M:%S’,
                filename=‘myapp.log’,
                filemode=‘w’)
    
logging.debug(‘This is debug message’)
logging.info(‘This is info message’)
logging.warning(‘This is warning message’)

 

./myapp.log文件中内容为:
Sun, 24 May 2009 21:48:54 demo2.py[line:11] DEBUG This is debug message
Sun, 24 May 2009 21:48:54 demo2.py[line:12] INFO This is info message
Sun, 24 May 2009 21:48:54 demo2.py[line:13] WARNING This is warning message

logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,’w’或’a’
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
 %(levelno)s: 打印日志级别的数值
 %(levelname)s: 打印日志级别名称
 %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
 %(filename)s: 打印当前执行程序名
 %(funcName)s: 打印日志的当前函数
 %(lineno)d: 打印日志的当前行号
 %(asctime)s: 打印日志的时间
 %(thread)d: 打印线程ID
 %(threadName)s: 打印线程名称
 %(process)d: 打印进程ID
 %(message)s: 打印日志信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略

3.将日志同时输出到文件和屏幕

import logging

logging.basicConfig(level=logging.DEBUG,
                format=‘%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s’,
                datefmt=‘%a, %d %b %Y %H:%M:%S’,
                filename=‘myapp.log’,
                filemode=‘w’)

#################################################################################################
#定义一个StreamHandler,将INFO级别或更高的日志信息打印到标准错误,并将其添加到当前的日志处理对象#
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter(‘%(name)-12s: %(levelname)-8s %(message)s’)
console.setFormatter(formatter)
logging.getLogger().addHandler(console)
#################################################################################################

logging.debug(‘This is debug message’)
logging.info(‘This is info message’)
logging.warning(‘This is warning message’)

 

屏幕上打印:
root        : INFO     This is info message
root        : WARNING  This is warning message

./myapp.log文件中内容为:
Sun, 24 May 2009 21:48:54 demo2.py[line:11] DEBUG This is debug message
Sun, 24 May 2009 21:48:54 demo2.py[line:12] INFO This is info message
Sun, 24 May 2009 21:48:54 demo2.py[line:13] WARNING This is warning message

4.logging之日志回滚

import logging
from logging.handlers import RotatingFileHandler

#################################################################################################
#定义一个RotatingFileHandler,最多备份5个日志文件,每个日志文件最大10M
Rthandler = RotatingFileHandler(‘myapp.log’, maxBytes=10*1024*1024,backupCount=5)
Rthandler.setLevel(logging.INFO)
formatter = logging.Formatter(‘%(name)-12s: %(levelname)-8s %(message)s’)
Rthandler.setFormatter(formatter)
logging.getLogger().addHandler(Rthandler)
################################################################################################

从上例和本例可以看出,logging有一个日志处理的主对象,其它处理方式都是通过addHandler添加进去的。
logging的几种handle方式如下:

 

logging.StreamHandler: 日志输出到流,可以是sys.stderr、sys.stdout或者文件
logging.FileHandler: 日志输出到文件

日志回滚方式,实际使用时用RotatingFileHandler和TimedRotatingFileHandler
logging.handlers.BaseRotatingHandler
logging.handlers.RotatingFileHandler
logging.handlers.TimedRotatingFileHandler

logging.handlers.SocketHandler: 远程输出日志到TCP/IP sockets
logging.handlers.DatagramHandler:  远程输出日志到UDP sockets
logging.handlers.SMTPHandler:  远程输出日志到邮件地址
logging.handlers.SysLogHandler: 日志输出到syslog
logging.handlers.NTEventLogHandler: 远程输出日志到Windows NT/2000/XP的事件日志
logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
logging.handlers.HTTPHandler: 通过”GET”或”POST”远程输出到HTTP服务器

 

由于StreamHandler和FileHandler是常用的日志处理方式,所以直接包含在logging模块中,而其他方式则包含在logging.handlers模块中,
上述其它处理方式的使用请参见python2.5手册!

5.通过logging.config模块配置日志

#logger.conf

###############################################

[loggers]
keys=root,example01,example02

[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0

###############################################

[handlers]
keys=hand01,hand02,hand03

[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=(‘myapp.log’, ‘a’)

[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form02
args=(‘myapp.log’, ‘a’, 10*1024*1024, 5)

###############################################

[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S

[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=

上例3:

import logging
import logging.config

logging.config.fileConfig(“logger.conf”)
logger = logging.getLogger(“example01”)

logger.debug(‘This is debug message’)
logger.info(‘This is info message’)
logger.warning(‘This is warning message’)

上例4:

import logging
import logging.config

logging.config.fileConfig(“logger.conf”)
logger = logging.getLogger(“example02”)

logger.debug(‘This is debug message’)
logger.info(‘This is info message’)
logger.warning(‘This is warning message’)

6.logging是线程安全的

转自:http://blog.csdn.net/azhao_dn/article/details/7320186

log4j中自定义append介绍

 log4j  log4j中自定义append介绍已关闭评论
5月 282015
 

记录下:

Apache Log4j 架构 

Apache Log4j是当前在J2EE和J2SE开发中用得最多的日志框架(几乎所有项目都用它),因为它具有出色的性能、灵活的配置以及丰富的功能,并且在业务有特殊的要求时,可以使用自定义组件来代替框架中已有的组件来满足要求。 

log4j组件介绍 
Log4j主要有三个组件: 
     

  • Logger:负责供客户端代码调用,执行debug(Object msg)、info(Object msg)、warn(Object msg)、error(Object msg)等方法。
  • Appender:负责日志的输出,Log4j已经实现了多种不同目标的输出方式,可以向文件输出日志、向控制台输出日志、向Socket输出日志等。
  • Layout:负责日志信息的格式化。

Logger 层级介绍 
Logger的层级是logger名字指定的,如x.y 表示两层,x层和y层,x是y的父层级,x.y所在层级是y层级 

log4j.additivity.* = false : 表示当前logger不需要打到父层级所指定的appender,只打到当前的appender; 
      默认true:表示当前logger将打印日志到当前的appender及所有的父层级所指定的appender 

Layout有多种 
最常用且最灵活的输出格式是: org.apache.log4j.PatternLayout 
可以用以下的各项进行组合配置: 

  • %c   logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间。
  • %C  调用logger的类的全名(包含包路径)。
  • %d  日志记录时间,{<日期格式>}使用ISO8601定义的日期格式。
  • %F  调用logger的源文件名。
  • %l    日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
  • %L   调用logger的代码行 %m   输出消息。
  • %M   调用logger的方法名。
  • %n   当前平台下的换行符。
  • %p   该条日志的优先级。
  • %r   从程序启动时到记录该条日志时已经经过的毫秒数。
  • %t  产生该日志事件的线程名。
  • %x   按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志。
  • %X   按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志。
  • %%   显示一个百分号。)

执行顺序及关系 
调用Log4j输出日志时,调用各个组件的顺序:

  • 1、日志信息传入 Logger。
  • 2、将日志信息封装成 LoggingEvent 对象并传入 Appender。
  • 3、在 Appender 中调用 Filter 对日志信息进行过滤,调用 Layout 对日志信息进行格式化,然后输出。

图示: 

实现自定义log4j Appender 
明白了log4j的结构关系实现自定义的log4j appender就迎刃而解了 
继承log4j公共的基类:AppenderSkeleton 
打印日志核心方法:abstract protected void append(LoggingEvent event); 
初始化加载资源:public void activateOptions(),默认实现为空 
释放资源:public void close() 
是否需要按格式输出文本:public boolean requiresLayout() 
正常情况下我们只需要覆盖append方法即可。然后就可以在log4j中使用了 

demo代码: 

Java代码  收藏代码

  1. import org.apache.log4j.AppenderSkeleton;  
  2. import org.apache.log4j.spi.LoggingEvent;  
  3.   
  4. public class HelloAppender extends AppenderSkeleton {  
  5.   
  6.     private String account ;  
  7.       
  8.     @Override  
  9.     protected void append(LoggingEvent event) {  
  10.         System.out.println(“Hello, “ + account + ” : “+ event.getMessage());  
  11.     }  
  12.   
  13.     @Override  
  14.     public void close() {  
  15.         // TODO Auto-generated method stub  
  16.   
  17.     }  
  18.   
  19.     @Override  
  20.     public boolean requiresLayout() {  
  21.         // TODO Auto-generated method stub  
  22.         return false;  
  23.     }  
  24.   
  25.     public String getAccount() {  
  26.         return account;  
  27.     }  
  28.   
  29.     public void setAccount(String account) {  
  30.         this.account = account;  
  31.     }  
  32. }  
Java代码  收藏代码

  1. public static void main(String[] args) {  
  2.     Log log = LogFactory.getLog(“helloLog”) ;  
  3.     log.info(“I am ready.”) ;  
  4. }  

引用
log4j.properties 配置 
log4j.logger.helloLog=INFO, hello 

log4j.appender.hello=HelloAppender 
log4j.appender.hello.account=World

执行main函数,输出结果 

Hello, World : I am ready.

转自:http://gemantic.iteye.com/blog/1234996

log4j patten格式

 log4j  log4j patten格式已关闭评论
9月 282014
 

网上收集的log4j patten的翻译,总结的很好,分享下:

 
参数 说明 例子
%c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间 log4j配置文件参数举例 输出显示媒介
假设当前logger名字空间是”a.b.c”
%c a.b.c
%c{2} b.c
%20c (若名字空间长度小于20,则左边用空格填充)
%-20c (若名字空间长度小于20,则右边用空格填充)
%.30c (若名字空间长度超过30,截去多余字符)
%20.30c (若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符)
%-20.30c (若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符)
%C 列出调用logger的类的全名(包含包路径) 假设当前类是”org.apache.xyz.SomeClass”
%C org.apache.xyz.SomeClass
%C{1} SomeClass
%d 显示日志记录时间,{<日期格式>}使用ISO8601定义的日期格式 %d{yyyy/MM/dd HH:mm:ss,SSS} 2005/10/12 22:23:30,117
%d{ABSOLUTE} 22:23:30,117
%d{DATE} 12 Oct 2005 22:23:30,117
%d{ISO8601} 2005-10-12 22:23:30,117
%F 显示调用logger的源文件名 %F MyClass.java
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数 %l MyClass.main(MyClass.java:129)
%L 显示调用logger的代码行 %L 129
%m 显示输出消息 %m This is a message for debug.
%M 显示调用logger的方法名 %M main
%n 当前平台下的换行符 %n Windows平台下表示rn
UNIX平台下表示n
%p 显示该条日志的优先级 %p INFO
%r 显示从程序启动时到记录该条日志时已经经过的毫秒数 %r 1215
%t 输出产生该日志事件的线程名 %t MyClass
%x 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志 假设某程序调用顺序是MyApp调用com.foo.Bar
%c %x – %m%n MyApp – Call com.foo.Bar.
com.foo.Bar – Log in Bar
MyApp – Return to MyApp.
%X 按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志。 %X{5} (记录代号为5的客户端的日志)
%% 显示一个百分号 %% %

 

apache官网原汁的版本在这里,供参考:

Conversion Pattern Description
c{precision}
logger{precision}

Outputs the name of the logger that published the logging event. The logger conversion specifier can be optionally followed byprecision specifier, which consists of a decimal integer, or a pattern starting with a decimal integer.

If a precision specifier is given and it is an integer value, then only the corresponding number of right most components of the logger name will be printed. If the precision contains other non-integer characters then the name will be abbreviated based on the pattern. If the precision integer is less than one the right-most token will still be printed in full. By default the logger name is printed in full.

Conversion Pattern Logger Name Result
%c{1} org.apache.commons.Foo Foo
%c{2} org.apache.commons.Foo commons.Foo
%c{1.} org.apache.commons.Foo o.a.c.Foo
%c{1.1.~.~} org.apache.commons.test.Foo o.a.~.~.Foo
%c{.} org.apache.commons.test.Foo ….Foo
C{precision}
class{precision}

Outputs the fully qualified class name of the caller issuing the logging request. This conversion specifier can be optionally followed byprecision specifier, that follows the same rules as the logger name converter.

Generating the class name of the caller (location information) is an expensive operation and may impact performance. Use with caution.

d{pattern}
date{pattern}

Outputs the date of the logging event. The date conversion specifier may be followed by a set of braces containing a date and time pattern string per SimpleDateFormat.

The predefined formats are DEFAULT, ABSOLUTE, COMPACT, DATE, ISO8601, and ISO8601_BASIC.

You can also use a set of braces containing a time zone id per java.util.TimeZone.getTimeZone. If no date format specifier is given then ISO8601 format is assumed.

Pattern Example
%d{DEFAULT} 2012-11-02 14:34:02,781
%d{ISO8601} 2012-11-02T14:34:02,781
%d{ISO8601_BASIC} 20121102T143402,781
%d{ABSOLUTE} 14:34:02,781
%d{DATE} 02 Nov 2012 14:34:02,781
%d{COMPACT} 20121102143402781
%d{HH:mm:ss,SSS} 14:34:02,781
%d{dd MMM yyyy HH:mm:ss,SSS} 02 Nov 2012 14:34:02,781
%d{HH:mm:ss}{GMT+0} 18:34:02
%d{UNIX} 1351866842
%d{UNIX_MILLIS} 1351866842781

%d{UNIX} outputs the UNIX time in seconds. %d{UNIX_MILLIS} outputs the UNIX time in milliseconds. The UNIX time is the difference, in seconds for UNIX and in milliseconds for UNIX_MILLIS, between the current time and midnight, January 1, 1970 UTC. While the time unit is milliseconds, the granularity depends on the operating system (Windows). This is an efficient way to output the event time because only a conversion from long to String takes place, there is no Date formatting involved.

enc{pattern}
encode{pattern>

Escape newlines and HTML special characters in the specified pattern.

Allows HTML to be safely logged.

enc{pattern}
encode{pattern}

Encodes special characters such as ‘n’ and HTML characters to help prevent log forging and some XSS attacks that could occur when displaying logs in a web browser. Anytime user provided data is logged, this can provide a safeguard.

A typical usage would encode the message

%enc{%m}

but user input could come from other locations as well, such as the MDC

%enc{%mdc{key}}

The replaced characters are:

Character Replacement
‘r’, ‘n’ Removed from the pattern
&, <, >, “, ‘, / Replaced with the corresponding HTML entity
ex|exception|throwable
  {[“none”
  |”full”
  |depth
  |”short”
  |”short.className”
  |”short.fileName”
  |”short.lineNumber”
  |”short.methodName”
  |”short.message”
  |”short.localizedMessage”]}

Outputs the Throwable trace bound to the LoggingEvent, by default this will output the full trace as one would normally find with a call to Throwable.printStackTrace().

You can follow the throwable conversion word with an option in the form %throwable{option}.

%throwable{short} outputs the first line of the Throwable.

%throwable{short.className} outputs the name of the class where the exception occurred.

%throwable{short.methodName} outputs the method name where the exception occurred.

%throwable{short.fileName} outputs the name of the class where the exception occurred.

%throwable{short.lineNumber} outputs the line number where the exception occurred.

%throwable{short.message} outputs the message.

%throwable{short.localizedMessage} outputs the localized message.

%throwable{n} outputs the first n lines of the stack trace.

Specifying %throwable{none} or %throwable{0} suppresses output of the exception.

F
file

Outputs the file name where the logging request was issued.

Generating the file information (location information) is an expensive operation and may impact performance. Use with caution.

highlight{pattern}{style}

Adds ANSI colors to the result of the enclosed pattern based on the current event’s logging level.

The default colors for each level are:

Level ANSI color
FATAL Bright red
ERROR Bright red
WARN Yellow
INFO Green
DEBUG Cyan
TRACE Black (looks dark grey)

The color names are ANSI names defined in the AnsiEscape class.

The color and attribute names and are standard, but the exact shade, hue, or value.

Color table

Intensity Code 0 1 2 3 4 5 6 7
Normal Black Red Green Yellow Blue Magenta Cyan White
Bright Black Red Green Yellow Blue Magenta Cyan White

You can use the default colors with:

%highlight{%d [%t] %-5level: %msg%n%throwable}

You can override the default colors in the optional {style} option. For example:

%highlight{%d [%t] %-5level: %msg%n%throwable}{FATAL=white, ERROR=red, WARN=blue, INFO=black, DEBUG=green, TRACE=blue}

You can highlight only the a portion of the log event:

%d [%t] %highlight{%-5level: %msg%n%throwable}

You can style one part of the message and highlight the rest the log event:

%style{%d [%t]}{black} %highlight{%-5level: %msg%n%throwable}

You can also use the STYLE key to use a predefined group of colors:

%highlight{%d [%t] %-5level: %msg%n%throwable}{STYLE=Logback}

The STYLE value can be one of:

Style Description
Default See above
Logback
Level ANSI color
FATAL Blinking bright red
ERROR Bright red
WARN Red
INFO Blue
DEBUG Normal
TRACE Normal
K{key}
map{key}
MAP{key}

Outputs the entries in a MapMessage, if one is present in the event. The K conversion character can be followed by the key for the map placed between braces, as in %K{clientNumber} where clientNumber is the key. The value in the Map corresponding to the key will be output. If no additional sub-option is specified, then the entire contents of the Map key value pair set is output using a format {{key1,val1},{key2,val2}}

l
location

Outputs location information of the caller which generated the logging event.

The location information depends on the JVM implementation but usually consists of the fully qualified name of the calling method followed by the callers source the file name and line number between parentheses.

Generating location information is an expensive operation and may impact performance. Use with caution.

L
line

Outputs the line number from where the logging request was issued.

Generating line number information (location information) is an expensive operation and may impact performance. Use with caution.

m
msg
message
Outputs the application supplied message associated with the logging event.
M
method

Outputs the method name where the logging request was issued.

Generating the method name of the caller (location information) is an expensive operation and may impact performance. Use with caution.

marker The name of the marker, if one is present.
n

Outputs the platform dependent line separator character or characters.

This conversion character offers practically the same performance as using non-portable line separator strings such as “n”, or “rn”. Thus, it is the preferred way of specifying a line separator.

p|level{level=labellevel=label, …}p|level{length=n}p|level{lowerCase=true|false}

Outputs the level of the logging event. You provide a level name map in the form “level=value, level=value” where level is the name of the Level and value is the value that should be displayed instead of the name of the Level.

For example:

%level{WARN=Warning, DEBUG=Debug, ERROR=Error, TRACE=Trace, INFO=Info}

Alternatively, for the compact-minded:

%level{WARN=W, DEBUG=D, ERROR=E, TRACE=T, INFO=I}

More succinctly, for the same result as above, you can define the length of the level label:

%level{length=1}

If the length is greater than a level name length, the layout uses the normal level name.

You can combine the two kinds of options:

%level{ERROR=Error, length=2}

This give you the Error level name and all other level names of length 2.

Finally, you can output lower-case level names (the default is upper-case):

%level{lowerCase=true}

r
relative
Outputs the number of milliseconds elapsed since the JVM was started until the creation of the logging event.
replace{pattern}{regex}{substitution}

Replaces occurrences of ‘regex’, a regular expression, with its replacement ‘substitution’ in the string resulting from evaluation of the pattern. For example, “%replace(%msg}{s}{}” will remove all spaces contained in the event message.

The pattern can be arbitrarily complex and in particular can contain multiple conversion keywords. For instance, “%replace{%logger %msg}{.}{/}” will replace all dots in the logger or the message of the event with a forward slash.

rEx[“none”|”short”|”full”|depth],[filters(packages)}
rException[“none”|”short”|”full”|depth],[filters(packages)}
rThrowable[“none”|”short”|”full”|depth],[filters(packages)}

The same as the %throwable conversion word but the stack trace is printed starting with the first exception that was thrown followed by each subsequent wrapping exception.

The throwable conversion word can be followed by an option in the form %rEx{short} which will only output the first line of the Throwable or %rEx{n} where the first n lines of the stacktrace will be printed. The conversion word can also be followed by “filters(packages)” where packages is a list of package names that should be suppressed from stack traces. Specifying %rEx{none} or %rEx{0} will suppress printing of the exception.

sn
sequenceNumber
Includes a sequence number that will be incremented in every event. The counter is a static variable so will only be unique within applications that share the same converter Class object.
style{pattern}{ANSI style}

Uses ANSI escape sequences to style the result of the enclosed pattern. The style can consist of a comma separated list of style names from the following table.

Style Name Description
Normal Normal display
Bright Bold
Dim Dimmed or faint characters
Underline Underlined characters
Blink Blinking characters
Reverse Reverse video
Hidden
Black or FG_Black Set foreground color to black
Red or FG_Red Set foreground color to red
Green or FG_Green Set foreground color to green
Yellow or FG_Yellow Set foreground color to yellow
Blue or FG_Blue Set foreground color to blue
Magenta or FG_Magenta Set foreground color to magenta
Cyan or FG_Cyan Set foreground color to cyan
White or FG_White Set foreground color to white
Default or FG_Default Set foreground color to default (white)
BG_Black Set background color to black
BG_Red Set background color to red
BG_Green Set background color to green
BG_Yellow Set background color to yellow
BG_Blue Set background color to blue
BG_Magenta Set background color to magenta
BG_Cyan Set background color to cyan
BG_White Set background color to white

For example:

%style{%d{ISO8601}}{black} %style{[%t]}{blue} %style{%-5level:}{yellow} %style{%msg%n%throwable}{green}

You can also combine styles:

%d %highlight{%p} %style{%logger}{bright,cyan} %C{1.} %msg%n

You can also use % with a color like %black, %blue, %cyan, and so on. For example:

%black{%d{ISO8601}} %blue{[%t]} %yellow{%-5level:} %green{%msg%n%throwable}

t
thread
Outputs the name of the thread that generated the logging event.
x
NDC
Outputs the Thread Context Stack (also known as the Nested Diagnostic Context or NDC) associated with the thread that generated the logging event.
X{key}
mdc{key}
MDC{key}

Outputs the Thread Context Map (also known as the Mapped Diagnostic Context or MDC) associated with the thread that generated the logging event. The X conversion character can be followed by the key for the map placed between braces, as in %X{clientNumber} where clientNumber is the key. The value in the MDC corresponding to the key will be output. If no additional sub-option is specified, then the entire contents of the MDC key value pair set is output using a format {{key1,val1},{key2,val2}}

See the ThreadContext class for more details.

u{“RANDOM” | “TIME”}
uuid
Includes either a random or a time-based UUID. The time-based UUID is a Type 1 UUID that can generate up to 10,000 unique ids per millisecond, will use the MAC address of each host, and to try to insure uniqueness across multiple JVMs and/or ClassLoaders on the same host a random number between 0 and 16,384 will be associated with each instance of the UUID generator Class and included in each time-based UUID generated. Because time-based UUIDs contain the MAC address and timestamp they should be used with care as they can cause a security vulnerability.
xEx{“none”|”short”|”full”|depth],[filters(packages)}
xException[“none”|”short”|”full”|depth],[filters(packages)}
xThrowable[“none”|”short”|”full”|depth],[filters(packages)}

The same as the %throwable conversion word but also includes class packaging information.

At the end of each stack element of the exception, a string containing the name of the jar file that contains the class or the directory the class is located in and the “Implementation-Version” as found in that jar’s manifest will be added. If the information is uncertain, then the class packaging data will be preceded by a tilde, i.e. the ‘~’ character.

The throwable conversion word can be followed by an option in the form %xEx{short} which will only output the first line of the Throwable or %xEx{n} where the first n lines of the stacktrace will be printed. The conversion word can also be followed by “filters(packages)” where packages is a list of package names that should be suppressed from stack traces. Specifying %xEx{none} or %xEx{0} will suppress printing of the exception.

% The sequence %% outputs a single percent sign.

 Posted by at 上午11:12  Tagged with:

log4j日志输出性能优化

 log4j  log4j日志输出性能优化已关闭评论
9月 122014
 

1、log4j已成为大型系统必不可少的一部分,log4j可以很方便的帮助我们在程序的任何位置输出所要打印的信息,便于我们对系统在调试阶段和正式运行阶段对问题分析和定位。由于日志级别的不同,对系统的性能影响也是有很大的差距,日志级别越高,性能越高。 

2、log4j主要分为error,warn,info,debug四个级别,也是使用最多的四种,日志级别从左至右依次增加。 

3、log4j对系统性能的影响程度主要体现在以下几方面:   
  a、日志输出的目的地,输出到控制台的速度比输出到文件系统的速度要慢。 
   b、日志输出格式不一样对性能也会有影响,如简单输出布局(SimpleLayout)比格式化输出布局(PatternLayout)输出速度要快。可以根据需要尽量采用简单输出布局格式输出日志信息。 
   c、日志级别越低输出的日志内容就越多,对系统系能影响很大。 
   d、日志输出方式的不同,对系统系能也是有一定影响的,采用异步输出方式比同步输出方式性能要高。 
   e、每次接收到日志输出事件就打印一条日志内容比当日志内容达到一定大小时打印系能要低。 

4、针对以上几点对系能的影响中的第4,5点,对日志配置文件做如下配置: 
   a、设置日志缓存,以及缓存大小 
     

Java代码  收藏代码

  1. log4j.appender.A3.BufferedIO=true   
  2.      #Buffer单位为字节,默认是8K,IO BLOCK大小默认也是8K    
  3.      log4j.appender.A3.BufferSize=8192   

    
  以上配置说明,当日志内容达到8k时,才会将日志输出到日志输出目的地。 
  
b、设置日志输出为异步方式 

Java代码  收藏代码

  1. <appender name=“DRFOUT” class=“org.apache.log4j.DailyRollingFileAppender”>    
  2.      <param name=“File” value=“logs/brws.log” />    
  3.      <param name=“Append” value=“true” />    
  4.      <param name=“DatePattern” value=“yyyy_MM_dd’.'” />    
  5.      <layout class=“org.apache.log4j.PatternLayout”>    
  6.          <param name=“ConversionPattern” value=“%d [%t] %-5p %l %x – %m%n” />    
  7.      </layout>    
  8.  </appender>    
  9.   
  10.  <appender name=“ASYNCOUT” class=“org.apache.log4j.AsyncAppender”>    
  11.      <param name=“BufferSize” value=“512” />    
  12.    <appender-ref ref=“DRFOUT” />    
  13.  </appender>    

同步情况:各线程直接获得输出流进行输出(线程间不需要同步)。 
异步情况:1.各线程将日志写到缓存,继续执行下面的任务(这里是异步的) 
          
2.日志线程发现需要记日志时独占缓存(与此同时各线程等待,此时各线程是被阻塞住的),从缓存中取出日志信息,获得输出流进行输出,将缓存解锁(各线程收到提醒,可以接着写日志了) 

   众所周知,磁盘IO操作、网络IO操作、JDBC操作等都是非常耗时的,日志输出的主要性能瓶颈也就是在写文件、写网络、写JDBC的时候。日志是肯定要记的,而要采用异步方式记,也就只有将这些耗时操作从主线程当中分离出去才真正的实现性能提升,也只有在线程间同步开销小于耗时操作时使用异步方式才真正有效 ! 

    现在我们接着分别来看看这几种记录日志的方式: 

    a、将日志记录到本地文件 同样都是写本地文件Log4j本身有一个buffer处理入库,采用异步方式并不一定能提高性能(主要是如何配置好缓存大小);而线程间的同步开销则是非常大的!因此在使用本地文件记录日志时不建议使用异步方式。    
    b、将日志记录到JMS JMS本身是支持异步消息的,如果不考虑JMS消息创建的开销,也不建议使用异步方式。     
   c、将日子记录到SOCKET 将日志通过Socket发送,纯网络IO操作不需要反馈,因此也不会耗时  
    d、将日志记录到数据库 众所周知JDBC是几种方式中最耗时的:网络、磁盘、数据库事务,都使JDBC操作异常的耗时,在这里采用异步方式入库倒是一个不错的选择。    
   e、将日志记录到SMTP 同JDBC 


5、异步输出日志工作原理
   
   AsyncAppender采用的是生产者消费者的模型进行异步地将Logging Event送到对应的Appender中。 

a、 生产者:外部应用了Log4j的系统的实时线程,实时将Logging Event传送进AsyncAppender里 
b、 中转:Buffer和DiscardSummary 
c、 消费者:Dispatcher线程和appenders
 
工作原理: 

1) Logging Event进入AsyncAppender,AsyncAppender会调用append方法,在append方法中会去把logging Event填入Buffer中,当消费能力不如生产能力时,AsyncAppender会把超出Buffer容量的Logging Event放到DiscardSummary中,作为消费速度一旦跟不上生成速度,中转buffer的溢出处理的一种方案。 

2)  AsyncAppender有个线程类Dispatcher,它是一个简单的线程类,实现了Runnable接口。它是AsyncAppender的后台线程。 

Dispatcher所要做的工作是: 

① 锁定Buffer,让其他要对Buffer进行操作的线程阻塞。 

② 看Buffer的容量是否满了,如果满了就将Buffer中的Logging Event全部取出,并清空Buffer和DiscardSummary;如果没满则等待Buffer填满Logging Event,然后notify Disaptcher线程。 

③ 将取出的所有Logging Event交给对应appender进行后面的日志信息推送。 

以上是AsyncAppender类的两个关键点:append方法和Dispatcher类,通过这两个关键点实现了异步推送日志信息的功能,这样如果大量的Logging Event进入AsyncAppender,就可以游刃有余地处理这些日志信息了。

 Posted by at 上午9:50  Tagged with:

log4j DatePattern 解惑(转)

 log4j  log4j DatePattern 解惑(转)已关闭评论
3月 202013
 

log4j.appender.Root=org.apache.log4j.DailyRollingFileAppender
log4j.appender.Root.File=../logs/blog
log4j.appender.Root.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.Root.layout=org.apache.log4j.PatternLayout  
log4j.appender.Root.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH:mm:ss} [%c.%M:%L]  %m%n

 

 

这样的方式可以在tomcat/logs/ 下生成 如:blog_2009_11_12.log这样的log文件,网上都是这样说的,但实际上自己做的时候发现生成的老是  blog这样一个文件  没后缀,本以为会生成blog_2009_11_12.log这样的,怎么试都不对,快郁闷死了,后来改了一下我的电脑的时间,改到13号,发现这时生成了一个blog_2009_11_12.log

 

后来试了下,总算明白了 log4j会先生成blog这样一个文件,然后当这一天过去的时候,生成一个新的blog,然后把原来的保存为加上日期格式后缀的文件(或者是把原来的挪到新的,把新的改变叫blog_2009_11_12.log 没去研究)

转自: http://renxiangzyq.iteye.com/blog/515325

 

 

log4j DatePattern格式

参考: http://my.oschina.net/heguangdong/blog/80849

DatePattern

Rollover schedule

Example

'.'yyyy-MM

Rollover at the beginning of each month

At midnight of May 31st, 2002 /foo/bar.log will be copied to /foo/bar.log.2002-05 . Logging for the month of June will be output to /foo/bar.log until it is also rolled over the next month.

'.'yyyy-ww

Rollover at the first day of each week. The first day of the week depends on the locale.

Assuming the first day of the week is Sunday, on Saturday midnight, June 9th 2002, the file /foo/bar.logwill be copied to /foo/bar.log.2002-23 . Logging for the 24th week of 2002 will be output to /foo/bar.log until it is rolled over the next week.

'.'yyyy-MM-dd

Rollover at midnight each day.

At midnight, on March 8th, 2002, /foo/bar.log will be copied to /foo/bar.log.2002-03-08 . Logging for the 9th day of March will be output to /foo/bar.loguntil it is rolled over the next day.

'.'yyyy-MM-dd-a

Rollover at midnight and midday of each day.

At noon, on March 9th, 2002, /foo/bar.log will be copied to /foo/bar.log.2002-03-09-AM . Logging for the afternoon of the 9th will be output to /foo/bar.log until it is rolled over at midnight.

'.'yyyy-MM-dd-HH

Rollover at the top of every hour.

At approximately 11:00.000 o'clock on March 9th, 2002,/foo/bar.log will be copied to /foo/bar.log.2002-03-09-10 . Logging for the 11th hour of the 9th of March will be output to /foo/bar.log until it is rolled over at the beginning of the next hour.

'.'yyyy-MM-dd-HH-mm

Rollover at the beginning of every minute.

At approximately 11:23,000, on March 9th, 2001, /foo/bar.log will be copied to /foo/bar.log.2001-03-09-10-22 . Logging for the minute of 11:23 (9th of March) will be output to /foo/bar.log until it is rolled over the next minute

Syslog配置及使用简介

 log  Syslog配置及使用简介已关闭评论
3月 202013
 

 

  1. Syslog简介

Syslog常被称作系统日志,在80年代作为sendmail的一部分而发布,由于其可用性,现在已成为用来在internet中传递日志信息的事实上的标准。这些传递日志的程序或数据库同时也被称作syslogSyslog是主从式的协议,syslog发送端发送一些小的文字信息到syslog接收端,接收端根据配置文件把收到的信息进行存储或者处理,或者再次进行转发。

Syslog通常被用作系统信息管理,由于其已在大多数系统上实现,所以它可以把不同类型主机上的信息集中整合到一起。但是它仍然有许多缺陷,表现在下面几个方面:Syslog的传输是通过UDP或者TCP传输,安全性并不可靠。一般可以通过ssl加密壳来完成加密;syslog的实时性不好,只能通过更改配置加以改进。所以syslog主要用在安全性要求不高,实时性不强的地方。

  1. Syslog协议

syslog使用UDP协议作为它的传输层协议,其默认使用UDP端口514

2.1. syslog体系结构

syslog模糊了发送方、接收方,设备、中继以及收集器的区别,一台设备可以同时是某种日志信息的中继、也可以是另外某种信息的收集器,同时可以作为发送者发送日志:

  • 发送方发送日志信息至某个主机,并不知道这台主机会如何处理这些日志。

  • 发送方可以通过配置,把同一条日志同时发送给多个接收者。

  • 中继可以发送所有或者部分信息给后序接收者,这种情况下它不完全是中继,也是一个收集信息者。

  • 中继可以产生自己的日志信息发送给后序接收者,这种情况下它也是一个产生信息的设备。

2.2. syslog包格式

Syslog包分为3个部分,PRI, HEADER,以及MSG,总长度不能超过1024个字节。

2.2.1 PRI

PRIpriority的缩写,它代表了facility以及severity,即代表消息来源以及消息的严重程度。它必须是12或者3个十进制字符,用‘<’,‘>’括起后组成的串,它是由facility以及severity构成,组成的方法是把facility的值乘以8,再加上severity的值。如facility取值local4(20), severirywarning(4),那么pri的值为<164>

Facility的取值如下表所示:

Numerical Code Facility

0 kernel messages

1 user-level messages

2 mail system

3 system daemons

4 security/authorization messages

5 messages generated internally by syslogd

6 line printer subsystem

7 network news subsystem

8 UUCP subsystem

9 clock daemon

10 security/authorization messages

11 FTP daemon

12 NTP subsystem

13 log audit

14 log alert

15 clock daemon (note 2)

16 local use 0 (local0)

17 local use 1 (local1)

18 local use 2 (local2)

19 local use 3 (local3)

20 local use 4 (local4)

21 local use 5 (local5)

22 local use 6 (local6)

23 local use 7 (local7)

 

严重等级分为:

Numerical Code Severity

0 Emergency: system is unusable

1 Alert: action must be taken immediately

2 Critical: critical conditions

3 Error: error conditions

4 Warning: warning conditions

5 Notice: normal but significant condition

6 Informational: informational messages

7 Debug: debug-level messages

2.2.2 HEADER部分

HEADER部分包含一个时间戳以及发送方的主机名或者ip地址,并且HEADER部分必须是一些可打印字符。

时间戳部分是格式为”Mmm dd hh:mm:ss”的本地时间,其中Mmm3个字母的英文缩写,如果日期小于10,必须用空格代替缺少的一个数字。

主机名部分一半使用主机名,如果没有的话可以使用IPv4或者IPv6的地址。需要注意的是主机名中不能包含任何空格。

时间戳和主机名后面都各自跟一个空格。

2.2.3 MSG部分

消息体部分一般包含生成消息的进程信息(TAG field)以及消息正文(CONTENT field)TAG部分主要是包含生成消息的进程信息,不能超过32个字符。消息体必须是一些可见字符,这部分就是消息的正文。TAGCONTENT之间的间隔用非字母表字母隔开,一般用”[“,”:”或者空格隔开。

  1. Syslog配置

3.1 概览

Syslog的全局配置文件一般存储在/etc/目录下,名为syslog.conf,由它指定syslogd程序对日志信息的处理。

配置文件由一系列的规则组成,一般每行一个规则,也可以使用反斜杠“来续行。

配置文件中每个规则都是由两部分组成,分别叫做选择符以及其对应的动作。选择符就是指上文介绍过的priority,包括facility以及severity,动作指匹配成功的话应执行的动作,如把日志写入管道,写入文件,或者再转发至另一台主机。

3.2选择符

选择符包括两部分,facility以及severity,两部分以一个点号”.”分割。这两个部分都大小写无关,并且可以使用上文中定义的数字来代替字符。

Facility部分可以使用下列关键字:auth, authpriv, cron, daemon, ftp, kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and local0 local7,或者使用其对应的数字。

Severity部分可以使用下列关键字:debug, info, notice, warning, warn (等同于warning), err, error(err), crit, alert, emerg, panic (emerg)

最初的BSD syslogd程序中,程序会把等于或者高于指定severity等级的日志按照指定动作来执行,现在syslogd程序中还包括一些有用的扩展:

  • *”号,可以代表任何facility或者severity,根据在”.”之前或之后判断。

  • ,”号,可以分割facility,这样可以把几个facility可以合并。但是severity不能这样合并。

  • ;”号,可以指定多个选择符,后面跟一个动作。处理得顺序是按照从前向后的顺序匹配选择符,并且后面的选择符可以覆盖前面的。因此可以使用这种特性来排除一些特殊的等级。

  • =”号,可以加在severity前面,表示准备匹配。

  • !”号,表示忽略这种severity或者更高等级,也可以与”=”号一起用。

3.3 动作

动作表示收到匹配的日志信息以后的处理动作,主要有写入文件,命名管道,终端,写入远程,提醒当前某些用户。

  1. 写入普通文件。后面加入日志文件的绝对路径即可。也可以添加“-”号来表示不立即写入。

如: *.=crit;kern.none /var/adm/critical

  1. 命名管道。通过加上”|”即可把日志写入命名管道。

如:mail,news.=info | /tmp/message.fifo

  1. 终端。只要动作中指定的文件是一个tty文件即可。

如:mail.=info /dev/tty12

  1. 远端机器。添加”@”符号,加上远端主机名/ip地址即可。syslog需要-h参数启动才会转发远端而来的消息。

如:kern.crit @finlandia

  1. 用户。直接在动作之中写入用户列表的名字即可。以逗号分割各个用户。

如:*.alert root,joey

  1. 所有已登陆用户。在动作中直接“*”号,表示把信息直接显示到已登陆用户的终端上。

如:*.=emerg *

  1. C语言中的syslog

GNU C库中包含了写syslog的一些库函数,使用这些函数可以方便的对syslog进行写操作。Glibc中主要包含以下syslog相关函数:

* openlog: 打开连接

* syslog; vsyslog: syslog

* closelog: 关闭连接

* setlogmask: 置标志,可以实现忽略某些消息

4.1 openlog

openlog函数在syslog.h中被声明,其原型如下:

void openlog (const char *ident, int option, int facility);

openlog不是必须被调用的,但是可以方便syslog的使用。

indent表示一串字符串,以后调用syslog写日志时这个字符串都会被自动添加到正文之前,一般用来表示当前程序的名字。如果indentNULL, 或者openlog没有被调用过,那么默认的名字是当前进程名。

option是一个位串,有以下掩码构成:

LOG_PERROR:记录至syslog的同时写到标准错误输出。默认不写入标准错误输出。

LOG_CONS:如果写入Syslog失败时写入控制台,默认不写入控制台。

LOG_PID:是否把进程ID也加入到信息中去。

LOG_NDELAY:打开的话,openlog会打开连接,否则syslog调用时才连接。

LOG_ODELAY:无意义,为兼容旧版本。

facility是此连接的默认的facility,参见上文facility相关内容。默认是LOG_USER

4.2 syslog

syslog就是记录日志的主函数,它通过写socket /dev/log(syslogd进程一直在监听此socket文件)实现写日志,其原型如下:

void syslog (int facility_priority, char *format, …)

 

facility_priority参数就是facilityseverity的集合,可以使用LOG_MAKEPRI宏来生成此参数:

LOG_MAKEPRI(LOG_USER, LOG_WARNING)

也可以直接使用syslog.h中定义的宏把facilityseverity连接起来即可。如:

syslog(LOG_WARN|LOG_LOCAL1, “message”);

其中LOG_LOCAL1宏的定义为(17<<3)

对应我们上文介绍的facility,有以下宏定义:

#define LOG_KERN (0<<3) /* kernel messages */

#define LOG_USER (1<<3) /* random user-level messages */

#define LOG_MAIL (2<<3) /* mail system */

#define LOG_DAEMON (3<<3) /* system daemons */

#define LOG_AUTH (4<<3) /* security/authorization messages */

#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */

#define LOG_LPR (6<<3) /* line printer subsystem */

#define LOG_NEWS (7<<3) /* network news subsystem */

#define LOG_UUCP (8<<3) /* UUCP subsystem */

#define LOG_CRON (9<<3) /* clock daemon */

#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */

#define LOG_FTP (11<<3) /* ftp daemon */

#define LOG_LOCAL0 (16<<3) /* reserved for local use */

#define LOG_LOCAL1 (17<<3) /* reserved for local use */

#define LOG_LOCAL2 (18<<3) /* reserved for local use */

#define LOG_LOCAL3 (19<<3) /* reserved for local use */

#define LOG_LOCAL4 (20<<3) /* reserved for local use */

#define LOG_LOCAL5 (21<<3) /* reserved for local use */

#define LOG_LOCAL6 (22<<3) /* reserved for local use */

#define LOG_LOCAL7 (23<<3) /* reserved for local use */

对应严重等级的宏有:

LOG_EMERG

LOG_ALERT

LOG_CRIT

LOG_ERR

LOG_WARNING

LOG_NOTICE

LOG_INFO

LOG_DEBUG

后面的参数部分是一个可变长参数,使用方法和常用的printf相同。

4.3 closelog

closelog函数会关闭当前连接,如果有连接打开的话。函数原型为:

void closelog (void);

4.4 setlogmask

setlogmask函数可以使后面调用syslog时忽略某些等级,与syslog.conf中配置的不同,如果被setlogmask函数忽略掉的日志,永远不会被发送至syslog。它的原型为:

int setlogmask (int mask)

其中mask是一个位串,其中每位表示一个等级,如果此位为1,那么syslog正常处理;如果为0,则忽略掉此信息。

通过宏LOG_MASK可以方便的表示可以忽略掉那些等级,如:

LOG_MASK(LOG_EMERG) | LOG_MASK(LOG_ERROR)

表示忽略EMERGERROR

或者使用~,如:

~(LOG_MASK(LOG_INFO))

表示忽略INFO以外的等级。

也可以使用宏LOG_UPTO,表示某等级或者此等级以上。

 

4.5例子

#include <syslog.h>

 

setlogmask (LOG_UPTO (LOG_NOTICE));

openlog ("exampleprog", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

syslog (LOG_NOTICE, "Program started by User %d", getuid ());

syslog (LOG_INFO, "A tree falls in a forest");

closelog ();

  1. 参考文献

1. BSD syslog protocol, RFC 3164, http://www.unix.com.ua/rfc/rfc3164.html

2. GNU C lib: http://www.gnu.org/software/libtool/manual/libc/Submitting-Syslog-Messages.html

3. http://www.hackinglinuxexposed.com/articles/20030220.html

 

 Posted by at 下午5:33  Tagged with:

解决 WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).

 log4j  解决 WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).已关闭评论
3月 142013
 

在spring的web项目中常常会在tomcat启动的时候出现这种提示: 

引用
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). 
log4j:WARN Please initialize the log4j system properly.



 方法: 

把log4j的配置org.springframework.web.util.Log4jConfigListener放到org.springframework.web.context.ContextLoader之前,就可以解决这个问题了。 
 

Xml代码  收藏代码

  1. <!– 以下3项参数与log4j的配置相关 –>  
  2.       
  3.     <context-param>  
  4.         <param-name>log4jConfigLocation</param-name>  
  5.         <param-value>/WEB-INF/log4j.properties</param-value>  
  6.     </context-param>  
  7.       
  8.     <context-param>  
  9.         <param-name>log4jRefreshInterval</param-name>  
  10.         <param-value>60000</param-value>  
  11.     </context-param>  
  12.     <listener>  
  13.         <listener-class>  
  14.             org.springframework.web.util.Log4jConfigListener  
  15.         </listener-class>  
  16.     </listener>  
  17. <!– end –>  
  18.   
  19.     <listener>  
  20.         <listener-class>  
  21.             org.springframework.web.context.ContextLoaderListener  
  22.         </listener-class>  
  23.     </listener>  

 

如以上方法还未解决问题,问题可能出在 log4j.rootLogger未配置。

 log4j.properties文件中添加如下配置即可:

log4j.rootLogger=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern=%5p [%t] (%F:%L) - %m%n