一天,python搞个分析NGINX日志的脚本
准备给ZABBIX用的。
统计接口访问字次,平均响应时间,4XX,5XX次数
以后可以再改进。。
#!/usr/bin/env python
# coding: utf-8
###################################
# User:chengang #
# Email:aguncn@163.com #
# Date:2016-02-25 #
###################################
import time
import datetime
import sys
import os
import os.path
import re
import json
class NginxLog(object):
def __init__(self, log_file, interface_list, seek_file):
self.log_file = log_file
self.interface_list = interface_list
self.seek_file = seek_file
# 将输出编码成json格式
def jsonFormat(self, python_data):
json_data = json.dumps(python_data, indent=2)
return json_data
# 获取电脑主机名
def hostname(self):
sys = os.name
if sys == 'nt':
hostname = os.getenv('computername')
return hostname
elif sys == 'posix':
host = os.popen('echo $HOSTNAME')
try:
hostname = host.read()
return hostname
finally:
host.close()
else:
return 'Unkwon hostname'
# 将读过的文件游标写入临时文件
def writeSeek(self, seek):
with open(self.seek_file,'w') as f:
f.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))+"\n")
f.write(str(seek)+"\n")
# 读出新生成的日志条目
def LogRead(self):
# 如果第一次运行,或是删除临时文件,从头运行,否则,从上次读取之后运行
# 0代表从头开始,1代表当前位置,2代表文件最末尾位置。
if os.path.exists(self.seek_file):
with open(self.seek_file) as f:
seek_tmp = f.readlines()
seek_old = int(seek_tmp[1].strip())
else:
seek_old = 0
with open(self.log_file) as f:
#记录当前最新文件游标
f.seek(0,2)
seek_now = f.tell()
# 读取上次读完之后的日志条目
if seek_now >= seek_old:
f.seek(seek_old,0)
chunk = f.read(seek_now-seek_old)
# 也可以考虑用xreadlines来实现
# for line in f.xreadlines():
# pass # do something
# 如果文件游标倒退,说明日志文件已轮循,从头开始
else:
f.seek(0,0)
chunk = f.read(seek_now)
# 将这次的游标写入临时文件
# self.writeSeek(seek_now)
return chunk
def LogStatistics(self):
#分析NGINX日志的正则表达示,如果日志格式更改,则需要相应作更改
#我拿到的日志样本和鹏龙的不一样,所以注释了一个字段
#field 0
field_remote_addr = r"?P<l_remote_addr>.*"
#field 1
field_remote_user = r"?P<l_remote_user>-"
#field 2
field_time_local = r"?P<l_time_local>\[.*\]"
#field 3
field_request = r"?P<l_request>\"[^\"]*\""
#field 4
field_status = r"?P<l_status>\"[^\"]*\""
#field 5
field_body_bytes_sent = r"?P<l_body_bytes_sent>\d+"
#field 6
field_http_refere = r"?P<l_http_refere>\"[^\"]*\""
#field 7
field_http_user_agent = r"?P<l_http_user_agent>\"[^\"]*\""
#field 8
#field_http_x_fowarded_for = r"?P<l_http_x_fowarded_for>\"[^\"]*\""
#field 8
field_all_cookie = r"?P<l_all_cookie>\"[^\"]*\""
#field 9
field_gzip_ratio = r"?P<l_gzip_ratio>\"[^\"]*\""
#field 10
field_upstream_addr = r"?P<l_upstream_addr>.*"
#field 11
field_bytes_sent = r"?P<l_bytes_sent>\d+"
#field 12
field_request_length = r"?P<l_request_length>\d+"
#field 13
field_request_time = r"?P<l_request_time>.*"
#以下为样例,方便调试
'''
10.25.162.22 - - [24/Feb/2016:14:09:25 +0800] "GET / HTTP/1.0" "200" 612 "-"
"-" "-" "-" - 846 54 0.000
10.25.162.22 - - [24/Feb/2016:14:09:35 +0800] "GET
/dsf/getRealTimeDatas?codes=&codeTypes=&_v=14562941753244588
HTTP/1.0" "200" 37
"http://asfdte/quote/dsftml" "Mozilla/5.0
(iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like
Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4" "-" "-" 10.25.174.34:30077
181 862 0.002
'''
# 正则匹配字段
nginxlog_pattern = re.compile(r"(%s)\s-\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)\s(%s)" \
%(field_remote_addr,field_remote_user,field_time_local,field_request,field_status, \
field_body_bytes_sent,field_http_refere,field_http_user_agent, \
field_all_cookie,field_gzip_ratio,field_upstream_addr,field_bytes_sent,field_request_length, \
field_request_time),re.VERBOSE)
#输出结果
result_list = []
# 未启用字段,作占位用
time_ns = datetime.datetime.now().microsecond
#转换成符合要求的时间秒格式
time_stamp = int(str(time.time())[0:10])
host_name = self.hostname()
# 多少个URL,就要循环读取多少次,算法粗糙,后面再想办法吧,因为如果只循环一次文件读取,则在里面要循环列表,还难理顺思路
for interface_item in self.interface_list:
# json格式样例 {"ns":470464001,"clock":1450368176,"value":"1","key":"macs.func.exeCount_0ms_50ms[104_202]","host":"SQSZ-L4"},
# 构造符合要求的字典
interface_item_dict_count = {}
interface_item_dict_avg_request_time = {}
interface_item_dict_2xx = {}
interface_item_dict_4xx = {}
interface_item_dict_5xx = {}
interface_item_dict_count['ns']=interface_item_dict_avg_request_time['ns']=interface_item_dict_2xx['ns']=interface_item_dict_4xx['ns']=interface_item_dict_5xx['ns']=time_ns
interface_item_dict_count['clock']=interface_item_dict_avg_request_time['clock']=interface_item_dict_2xx['clock']=interface_item_dict_4xx['clock']=interface_item_dict_5xx['clock']=time_stamp
interface_item_dict_count['host']=interface_item_dict_avg_request_time['host']=interface_item_dict_2xx['host']=interface_item_dict_4xx['host']=interface_item_dict_5xx['host']=host_name
interface_item_dict_count['key'] = interface_item + '_count'
interface_item_dict_count['value'] = 0
interface_item_dict_avg_request_time['key'] = interface_item + '_avg_request_time'
interface_item_dict_avg_request_time['value'] = 0
interface_item_dict_2xx['key'] = interface_item + '_2xx'
interface_item_dict_2xx['value'] = 0
interface_item_dict_4xx['key'] = interface_item + '_4xx'
interface_item_dict_4xx['value'] = 0
interface_item_dict_5xx['key'] = interface_item + '_5xx'
interface_item_dict_5xx['value'] = 0
hit_url_count = 0
for line in self.LogRead().split('\n'):
line_matchs = nginxlog_pattern.match(line)
if line_matchs!=None:
#匹配字段
allGroups = line_matchs.groups()
remote_addr = allGroups[0]
#切割出真正的URL
request_url = allGroups[3].split()[1].split('?')[0].split('/')[-1]
status_code = allGroups[4]
request_time = allGroups[13]
# 匹配URL之后进行数据结构操作
if interface_item == request_url:
hit_url_count += 1
interface_item_dict_count['value'] += 1
interface_item_dict_avg_request_time['value'] += float(request_time)
'):
interface_item_dict_2xx['value'] += 1
'):
interface_item_dict_4xx['value'] += 1
'):
interface_item_dict_5xx['value'] += 1
# 求平均请求反应时间
if interface_item_dict_avg_request_time['value'] != 0:
interface_item_dict_avg_request_time['value'] = interface_item_dict_avg_request_time['value'] / hit_url_count
#入总列表
result_list.append(interface_item_dict_count)
result_list.append(interface_item_dict_avg_request_time)
result_list.append(interface_item_dict_2xx)
result_list.append(interface_item_dict_4xx)
result_list.append(interface_item_dict_5xx)
return self.jsonFormat(result_list)
def resultOutput(self):
pass
def main():
#需要收集的url
interface_list = ['getIndexData', \
'getRealTimeDatas',
'hehel',]
#日志定位
log_file = 'd:\\demo\\sample.log'
# 临时文件游标文件
seek_file = 'd:\\demo\\log_check_seek.tmp'
nginx_log = NginxLog(log_file, interface_list, seek_file)
return_json_data = nginx_log.LogStatistics()
print return_json_data
if __name__ == "__main__":
main()

一天,python搞个分析NGINX日志的脚本的更多相关文章
- 利用python分析nginx日志
最近在学习python,写了个脚本分析nginx日志,练练手.写得比较粗糙,但基本功能可以实现. 脚本功能:查找出当天访问次数前十位的IP,并获取该IP来源,并将分析结果发送邮件到指定邮箱. 实现前两 ...
- 使用Docker快速部署ELK分析Nginx日志实践(二)
Kibana汉化使用中文界面实践 一.背景 笔者在上一篇文章使用Docker快速部署ELK分析Nginx日志实践当中有提到如何快速搭建ELK分析Nginx日志,但是这只是第一步,后面还有很多仪表盘需要 ...
- 烂泥:利用awstats分析nginx日志
本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看<烂泥:切割 ...
- elk实战分析nginx日志文档
elk实战分析nginx日志文档 架构: kibana <--- es-cluster <--- logstash <--- filebeat 环境准备:192.168.3.1 no ...
- elk平台分析nginx日志的基本搭建
一.elk套件介绍 ELK 由 ElasticSearch . Logstash 和 Kiabana 三个开源工具组成.官方网站: https://www.elastic.co/products El ...
- Awstats分析Nginx日志
1.nginx日志格式设定 log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$ ...
- hive分析nginx日志之UDF清洗数据
hive分析nginx日志一:http://www.cnblogs.com/wcwen1990/p/7066230.html hive分析nginx日志二:http://www.cnblogs.com ...
- awstat分析nginx日志
awstat分析nginx日志 http://lxw66.blog.51cto.com/5547576/1323712 server{ listen ; server_name localhost; ...
- shell脚本分析nginx日志
shell脚本分析nginx日志: name=`awk -F ',' '{print $13":"$32}' $file | awk -F ':' '{print $4}'`ech ...
随机推荐
- windows phone 8 开发系列(三)程序清单说明与配置
一 清单文件内容介绍 当我们先建了一个项目之后,我们可以看到vs自动会为我们创建了很多文件,正常人都会先一个个去翻看下每个文件都是干啥的,都主要写了些啥,在这些文件中,在Properies目录下面,我 ...
- 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计
本帖最后由 xinxincaijq 于 2013-1-9 10:27 编辑 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计 转自博客:http:// ...
- Android Audio Play Out Channel
1: 7嘴8舌 扬声器, 耳机, 和听筒 就是通过: audiomanager.setmode(AudioManager.MODE_IN_COMMUNICATION)audiomanager.setS ...
- OpenSUSE 安装并启动Tomcat
安装.用YsST2搜索tomcat安装就好了.不过版本肯定不如官网的新,笔者用的是7.0.42,最新的已经到8.X了. 启动.在服务管理器中找到tomcat,启动.
- js学习笔记一类型、值和变量
js的数据类型分为两类:原始类型和对象类型 原始类型包括数字.字符串和布尔值 js中有2个特殊的原始值:null(空)和undefined(未定义) 对象是属性的集合,每个属性都由名/值对组成 js的 ...
- 用Tupper自我指涉公式造图
塔珀自指公式是杰夫·塔珀(Jeff Tupper)发现的自指公式:此公式的二维图像与公式本身外观一样.此公式在众多数学与计算机科学课程里被用作绘制公式图像的练习作业. 公式最初于他2001年SIGGR ...
- Object.keys()
Object.keys(obj),返回一个数组,数组里是该obj可被枚举的所有属性名.请看示例: 示例一: function Pasta(grain, width, shape) { this.gra ...
- C/C++运算符优先级
运算符优先级从高至低 优先级 操作符 描述 例子 结合性 1 ()[]->.::++-- 调节优先级的括号操作符数组下标访问操作符通过指向对象的指针访问成员的操作符通过对象本身访问成员的操作符作 ...
- 【quartz】 各数据库创建脚本
QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息 QRTZ_CRON_TRIGGERS 存储 Cron Trigger,包括 Cron表达式和时区信息 ...
- TCP相关知识
1. TCP与TCP/IP协议族 TCP是TCP/IP协议族中运输层的一个协议.TCP/IP,即传输控制协议/网间协议,是一个工业标准的协议集,包含了运输层.网络层和链路层的协议,其结构如下图所示:其 ...