之前是用mysql数据库来保存用户的访问日志,现在已经超过2亿了,速度非常慢,还分了三张表,所以要换一种记录日志的方式。现在暂时没有时间做数据挖掘,要做的只是把日志先存起来。Sina介绍了一个不错的方案:直接用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命令就可以了。
转载请注明:爱开源 » mysql日志通过python发送到rsyslog