转换nginx日志模式_用Data-pipeline模式将nginx日志存储到elasticsearch中(1)

做运维的小伙伴应该都知道nginx日志的重要性,一般出现访问问题,我们可能第一时间要去看日志去分析问题,但除了协助我们排查问题外,如果对nginx日志进一步分析可以得到更有用的数据,例如可以监控某站点的http状态码、PV,UV情况,request_time和response_time等,如果辅助其它工具进一步分析可以预防一些安全问题,比如同一个IP的访问某页面超出了限制,我们可以设置策略发现后可以自动拒绝有危险的IP访问,这也是我们经常说的防刷功能,今天要跟大家分享的是如何将nginx日志存储到es中,存储的目的当时是为了更好的分析它,大家都知道,如果要存储到es中,数据必须是json格式的,但如果当前日志不是json格式的就需要进行一个转换,要把每行数据转成json格式的这里有几个问题要明确:

首先,access.log是不断增长的,这就需要有个程序能实时读取新的日志进行转换,这是第一个要解决的问题。

其次,对转换完的数据我们能不能直接存储到es中,答案是不建议,因为如果转一次存一次,在程序中我们势必要判断每次存储是否成功,在高并发的网站中日志的产生量是非常巨大的,这样一来会影响整体的效率,那怎么办?在这种情况下,最好的解决办法就是用消息队列的方式去解决,这里我们选择kafka,这个后续会说。

根据上面的内容大家可以看到其实在分析nginx日志的过程就是一个数据流的处理,这也是我们标题所说的data-pipline,pipline故名意思就是管道的意思,加一个data就是一个数据管道,我们就是要建立一个这样的管道将数据源源不断的产生出来,就像水管的水一样。

因为要解决的二个问题,今天我们先解决第一个,先实现access.log实时读取和转换成json格式,先看我们的access.log的文件内容:

111.20.21.22 - - [19/Dec/2016:12:00:30 +0800] "GET / HTTP/1.1" 502 602 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Geco) Chrome/54.0.2840.99 Safari/537.36"

1

111.20.21.22--[19/Dec/2016:12:00:30+0800]"GET / HTTP/1.1"502602"-""Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Geco) Chrome/54.0.2840.99 Safari/537.36"

划重点了,请看代码:

import time

import datetime

import json

import socket

def parse_log_line(line):

strptime = datetime.datetime.strptime

hostname = socket.gethostname()

time = line.split(' ')[3][1::]

entry = {}

entry['datetime'] = strptime(

time, "%d/%b/%Y:%H:%M:%S").strftime("%Y-%m-%d %H:%M")

entry['source'] = "{}".format(hostname)

entry['type'] = "www_access"

entry['log'] = "'{}'".format(line.rstrip())

return entry

def show_entry(entry):

temp = ",".join([

entry['datetime'],

entry['source'],

entry['type'],

entry['log']

])

log_entry = {'log': entry}

temp = json.dumps(log_entry)

print("{}".format(temp))

return temp

def follow(syslog_file):

syslog_file.seek(0, 2)

while True:

line = syslog_file.readline()

if not line:

time.sleep(0.1)

continue

else:

entry = parse_log_line(line)

if not entry:

continue

json_entry = show_entry(entry)

print(json_entry)

f = open("access.log", "rt")

follow(f)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

importtime

importdatetime

importjson

importsocket

defparse_log_line(line):

strptime=datetime.datetime.strptime

hostname=socket.gethostname()

time=line.split(' ')[3][1::]

entry={}

entry['datetime']=strptime(

time,"%d/%b/%Y:%H:%M:%S").strftime("%Y-%m-%d %H:%M")

entry['source']="{}".format(hostname)

entry['type']="www_access"

entry['log']="'{}'".format(line.rstrip())

returnentry

defshow_entry(entry):

temp=",".join([

entry['datetime'],

entry['source'],

entry['type'],

entry['log']

])

log_entry={'log':entry}

temp=json.dumps(log_entry)

print("{}".format(temp))

returntemp

deffollow(syslog_file):

syslog_file.seek(0,2)

whileTrue:

line=syslog_file.readline()

ifnotline:

time.sleep(0.1)

continue

else:

entry=parse_log_line(line)

ifnotentry:

continue

json_entry=show_entry(entry)

print(json_entry)

f=open("access.log","rt")

follow(f)

运行结果:

{

"log": {

"datetime": "2016-12-19 12:00",

"source": "iZ258ml0cx5Z",

"type": "www_access",

"log": "'111.20.21.22 - - [19/Dec/2016:12:00:30 +0800] \"GET / HTTP/1.1\" 502 602 \"-\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Geco) Chrome/54.0.2840.99 Safari/537.36\"'"

}

}

1

2

3

4

5

6

7

8

{

"log":{

"datetime":"2016-12-19 12:00",

"source":"iZ258ml0cx5Z",

"type":"www_access",

"log":"'111.20.21.22 - - [19/Dec/2016:12:00:30 +0800] \"GET / HTTP/1.1\" 502 602 \"-\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Geco) Chrome/54.0.2840.99 Safari/537.36\"'"

}

}

脚本整体逻辑是先将行日志转换成一个字典(parse_log_line()函数),然后将字典转成json格式(show_entry()函数),最后follow函数是开始从尾部读取日志文件注意seek(0,2)参数是2从文件底部读取。

写到这我们第一个问题就算是解决了,接下来的工作就是如果把数据传给kafka了,因为kafka本身就是一块比较大的内容限于篇幅我们下次继续,多谢各位观看,如果觉得还不错,还请帮转发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值