Python Tech

用rsyslog处理日志

之前是用mysql数据库来保存用户的访问日志,现在已经超过2亿了,速度非常慢,还分了三张表,要换一种记录日志的方式。现在暂时没有时间做数据挖掘,要做的只是把日志先存起来,所以直接用linux自带的rsyslog来做。用户访问时,以UDP的方式,将访问信息封装成JSON发到rsyslog的端口,rsyslog会以文本的方式直接记录下来。以后就可以用syslog-ng之类的工具写到mongo或其他数据库。

修改配置文件

新建一个配置文件:

$ sudo vi /etc/rsyslog.d/00-dmyz.conf

默认的日志格式是日期:主机:信息(datetime, host, msg),现在只需要保存msg,host和datetime之类都写在的msg里,以日期作为文件名来存放日志:


$template logFormat, "%rawmsg%\n"
$template DynaFile, "/var/log/%$YEAR%-%$MONTH%-%$DAY%.log"
$ActionFileDefaultTemplate logFormat
user.info            -?DynaFile

然后修改 /etc/rsyslog.conf 打开UDP端口用来接收日志:


# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

写入数据

python提供了socket,可以先用以下列方式测试写入是否正常:


import socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(simplejson.dumps("log_id": 1),('127.0.0.1',514))

如果一切正常,在/var/log/ 目录下会生成以当前日期作为文件名的.log文件,如果出错,最有可能是权限问题。还有,如果把生成的文件删除了,需要重启一次rsyslog服务,它才会重新生成。

以下是按天从mysql读出日志数据,发送到UDP 514端口的Python代码:


import socket
import simplejson
import datetime
from subprocess import Popen, PIPE

def select_logs_by_time():
    alchemy = AlchemyMysql('logs') #这里是读取mysql用的
    table = alchemy.query()
    i = 0
    while i <= 20:
        start_datetime = datetime.datetime.strptime('2012-02-10 00:00:00', "%Y-%m-%d %H:%M:%S") + datetime.timedelta(days=i)
        end_datetime = datetime.datetime.strptime('2011-02-10 23:59:59', "%Y-%m-%d %H:%M:%S") + datetime.timedelta(days=i)
        print str(start_datetime) + ' - ' + str(end_datetime)
        logs = table.select().where(table.c.date >= str(start_datetime)).where(table.c.date <= str(end_datetime)).execute()
        for log in logs:
            send_log(log)
        date_time = str(start_datetime).split(' ')[0]
        Popen(['cp','/var/log/dmyz/2012-06-14.log', '/var/log/dmyz/'+date_time+'.log'], stdout=PIPE)
        i = i+1

def send_log(log):
    data = { 
        "thread_id" : log['thread_id'],
        "site_id" : log['site_id'],
        "user_agent" : log['user_agent'],
        "url" : log['url'],
        "referer" : log['referer'],
        "user_id" : log['user_id'],
        "ip" : log['ip'],
        "elapsed_time" : log['elapsed_time'],
        # "unique" : log['unique']
    }
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client.sendto(simplejson.dumps(data),('127.0.0.1',514))

if __name__ == '__main__':
    select_logs_by_time()

效果是,现在每天近千万的PV,生成的日志文件是1G左右,用bzip2压缩后只有100多MB,需要统计今天的访问量用wc命令就可以了。

0 0 投票数
文章评分
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

3 评论
最新
最旧 最多投票
内联反馈
查看所有评论
alert(1)
11 年 前

网上搜rsyslog,居然直接搜出你这篇。

腾袭
12 年 前

一般的日志记录都是直接用文件记录的吧,用数据库来记录日志很不划算- –
ps. 突然发现在每个博文里好像看不到发表的日期,略蛋疼。