• 【原创】基于日志增量,统计qps,并基于ip排序


    • 增量统计日志行数(只统计上一秒)

    dns_qps.py

    #!/usr/bin/env python
    #_*_coding:utf-8_*_
    
    
    import datetime
    import re
    import os
    
    log_files = './dns_logs'  #填写要分析的源日志
    seek_files = './seek_log.tmp'  #生成的临时文件,只用于保存位置seek信息,建议放/tmp/下
    last_second = datetime.datetime.now() - datetime.timedelta(seconds=1)  #取上一秒的时间,因为当前秒可能日志取不全
    current_time = last_second.strftime('%d-%b-%Y %T')   #时间格式根据日志格式做修改
    #current_time = '17-Jun-2016 14:17:20'
    
    
    if not os.path.exists(seek_files):
        with open(seek_files, 'w+') as s:
            s.write(str(0))
    
    
    def write_file_end(log_files, seek_files):
        with open(log_files, 'r') as f:  #先找到log的最后字节位置
            f.seek(0, 2)  #seek(0)移动到文件起始、(0,2)移动到结尾
            end_seek = f.tell()
        with open(seek_files, 'w+') as s:
            s.write(str(end_seek))  #把log的最后字节位置记录到seek文件
    
    
    def get_count(log_files, begin):
        count = 0
        dns_pattern = re.compile(current_time+r'.(w+)(s+)'+"queries: info: client")  #这个正则要根据你的日志格式来,可以放到前边,声明一个变量,我这图省事了
        with open(log_files, 'r') as f:  #打开log,并移位到seek中记录的地方,从那开始读取行数并做累加,读完以后在更新seek文件到最新点
            f.seek(begin)
            for line in f.xreadlines():
                if dns_pattern.match(line):
                    count += 1
        print(count)
    
    
    if __name__ == '__main__':
        try:
            with open(seek_files, 'r') as t:
                if len(t.read()) == 0:  #seek文件为空,强制begin=0,不为空,begin就等于seek
                    begin = 0
                else:
                    t.seek(0)
                    begin = int(t.read())
            with open(log_files, 'r') as f:  #拿到end,end值为log文件的最后位置
                f.seek(0, 2)
                end = f.tell()
            if end < begin:  #因为日志定期会切分,切分后log的end将为0,此时begin强制为0,不然输出的count将为0
                begin = 0
            get_count(log_files, begin)  #得到上一秒的总行数
            write_file_end(log_files, seek_files)  #把日志最后的位置保存给seek文件,用于下一秒的获取
        except Exception, e:
            print(0)
    
    

    注意事项
    把这个脚本放在zabbix之类的监控里,一秒执行一次,就可以算出每秒(其实是上一秒)增量部分的行数了,然后zabbix拿着这个度数绘图

    # 运行脚本
    /usr/bin/python2.6 dns_qps.py
    

    下边更进一步,拿着这个增量,基于源ip,我们再做一个排序,把排序结果记录到一个log里

    • 增量统计日志(tcpdump出来的数据)并排序,记录日志

    dns_request_sort.py

    #!/usr/bin/env python
    #_*_coding:utf-8_*_
    
    
    import datetime
    import re
    import os
    import logging
    import sys
    
    
    master_dir = "/Data/logs/dns_qps/tcpdump_53"  #把tcpdump的数据放这个目录里,原生的tcpdump数据
    today = datetime.datetime.now().strftime('%Y%m%d')
    log_files = os.path.join(master_dir, today+'.log'),
    log_files = log_files[0]
    if not os.path.exists(log_files):
        sys.exit('Can not find logfile')
    
    # for tcpdump
    seek_files = '/tmp/seek_log_4_tcpdump_53.tmp'  #同理存放seek信息的
    last_second = datetime.datetime.now() - datetime.timedelta(seconds=1)  #取上一秒的时间,因为当前秒可能日志取不全
    current_time = last_second.strftime('%T')
    #current_time = '16:54:17'
    warning_num = 4  #设定阈值
    warning_log = "/Data/logs/dns_qps/dns_warning_sort.log"  #生成的排序ip的日志
    
    
    def Mylogger(msg, logfile, level='info'):
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s [%(levelname)s] %(message)s',
            filename=logfile,
            filemode='a+')
        if level == 'critical':
            logging.critical(msg)
        elif level == 'error':
            logging.error(msg)
        elif level == 'warn':
            logging.warn(msg)
        elif level == 'info':
            logging.info(msg)
        else:
            logging.debug(msg)
    
    
    if not os.path.exists(seek_files):
        with open(seek_files, 'w+') as s:
            s.write(str(0))
    
    
    def write_file_end(log_files, seek_files):
        with open(log_files, 'r') as f:  #先找到log的最后字节位置
            f.seek(0, 2)
            end_seek = f.tell()
        with open(seek_files, 'w+') as s:
            s.write(str(end_seek))  #把log的最后字节位置记录到seek文件
    
    
    def get_count(log_files, begin):
        dns_pattern = re.compile(current_time+r'.d+ IP (d+.d+.d+.d+).d+[sS]*')
        ip_list = []
        with open(log_files, 'r') as f:  #打开log,并移位到seek中记录的地方,从那开始读取行数并做累加,读完以后在更新seek文件到最新点
            f.seek(begin)
            for line in f.xreadlines():
                if dns_pattern.match(line):
                    ip_list.append(dns_pattern.match(line).groups()[0])  #groups()[0]是匹配的ip字段
        for item in set(ip_list):  #最后得到一个大列表,里边放着一秒内的多个ip,可能有重叠,set()去重并循环它,每个item就是一个ip
            if ip_list.count(item) >= warning_num:  #列表中出现的ip的数量超过阈值就记录日志
                Mylogger("%s %s 此IP: %s 访问达到 %d 次" % (today, current_time, item, ip_list.count(item)),
                         warning_log, level='warn')
    
    
    if __name__ == '__main__':
        try:
            with open(seek_files, 'r') as t:
                if len(t.read()) == 0:
                    begin = 0
                else:
                    t.seek(0)
                    begin = int(t.read())
            with open(log_files, 'r') as f:
                f.seek(0, 2)
                end = f.tell()
            if end < begin:  #因为日志定期会切分,切分后log的end将为0,此时begin强制为0,不然输出的count将为0
                begin = 0
            get_count(log_files, begin)
            write_file_end(log_files, seek_files)
        except Exception, e:
            pass
    

    最后附上跑tcpdump的那个脚本
    本来想用python的pypcap来抓取数据包,然后用dpkt来分析的,但测了一下,抓出来的东西都是乱码,就放弃了,直接用shell调用tcpdump脚本了
    while_53.sh

    #!/usr/bin/env bash
    
    master_dir="/Data/logs/dns_qps/tcpdump_53"
    device="em1"
    mkdir -p ${master_dir}
    chown -R zabbix.zabbix ${master_dir}
    
    sudo /bin/kill -9 `ps -ef|grep tcpdump|grep -v grep|awk '{print$2}'` 2>/dev/null 
    today=`date +%Y%m%d`
    sudo /usr/sbin/tcpdump -i ${device} -nn udp port 53|grep "> 10.*.53:" >> ${master_dir}/${today}.log &
    

    把2个脚本放到crontab跑起来

    00 00 * * * cd /Data/shell && sh while_53.sh  #这个每天重启一次tcpdump用于按天分割日志
    * * * * * cd /Data/shell && /usr/bin/python dns_request_sort.py  #没那么敏感的要求,一分钟跑一次足矣
    
    # 看下生成的日志
    2016-08-26 16:20:01,568 [WARNING] 20160826 16:20:00 此IP: 10.1.0.110 访问达到 70 次
    2016-08-26 16:21:01,616 [WARNING] 20160826 16:21:00 此IP: 10.1.0.110 访问达到 67 次
    2016-08-26 16:22:01,665 [WARNING] 20160826 16:22:00 此IP: 10.1.0.110 访问达到 68 次
    2016-08-26 16:23:01,714 [WARNING] 20160826 16:23:00 此IP: 10.1.0.110 访问达到 65 次
    2016-08-26 16:24:01,766 [WARNING] 20160826 16:24:00 此IP: 10.1.20.253 访问达到 100 次
    2016-08-26 16:24:01,766 [WARNING] 20160826 16:24:00 此IP: 10.1.0.110 访问达到 72 次
    2016-08-26 16:25:01,815 [WARNING] 20160826 16:25:00 此IP: 10.1.0.110 访问达到 59 次
    
  • 相关阅读:
    android最恶心的是什么?
    有谁熟悉WordPress不?
    迷茫了....
    这事儿SB了....
    软件可靠性测
    养生之道
    我学员的一个问题及其我对之的解答,关于lr返回值问题
    如何自动启动小键盘
    测试工程师工作流程概论
    异构数据库之间的导入导出[转载]
  • 原文地址:https://www.cnblogs.com/caseast/p/5810686.html
Copyright © 2020-2023  润新知