Python統計web應用的每個連接使用情況
阿新 • • 發佈:2017-10-02
日誌分析 nginx 功能
背景:前段時間接到一個需求,領導說他想要知道我們在生產環境中某系統的每個應用使用情況。
需求:
統計每個按鈕的點擊量;
不能影響生產環境;
數據要不斷遞增,而不是看某個時間段的;
數據要永久存放,不丟;
思路:我想這可以通過nginx的日誌來進行分析,每個action和後臺的nginx接到請求肯定是一對一的,那麽我們通過nginx的日誌,那這個需求就解決了;
方案:
分析nginx的請求日誌;
淩晨進行日誌分析,且數據不妨到生產環境;
做定時任務;
存放到mongodb;
總結:在每天淩晨進行日誌分析,把處理結果存放那個到線下mongodb數據庫中
代碼實現:
連接mongo代碼↓
#coding=utf-8 # auth: xinsir # date: 2017/10/02 # version:3.0 from pymongo import MongoClient import pickle #建立MongoDB數據庫連接 client = MongoClient(‘192.168.1.197‘,27017) #連接所需數據庫,test為數據庫名 db=client.nginxlog #連接所用集合,也就是我們通常所說的表,test為表名 collection=db.recording # 寫一個方法,用於反序列化數據 def Deserialization(name): Data = pickle.load(name) return Data # 寫一個方法,向mongo中存放數據 def InsterData(data): collection.insert(data) # 寫一個方法,用來查詢mongo中的數據 def SechMongo(link): for u in collection.find( {‘Link‘: link} ): return True else: return False # 寫一個方法,用來更新mongo中的數據 def Update(wherelink): data = collection.find_one({‘Link‘:wherelink}) collection.update({‘Link‘:wherelink},{‘$set‘:{‘cunt‘:int(data[‘cunt‘])+1}})
插入模版代碼↓
#coding=utf-8 # auth: xinsir # date: 2017/10/02 # version:3.0 #_*_ coding:utf-8 _*_ # 寫一個方法,用來導入請求連接的模版,在進行日誌分析之前,首先要對mongo集合中插入模版 import systemmongo ActionLog = ‘../nginxlog/result.txt‘ def Sech(File): SechDic = {} with open(File,‘r‘,encoding=‘UTF-8‘) as ActionLogFile: for line in ActionLogFile.readlines(): a = line.split(‘\t‘) b = a[-1].split(‘\n‘) del a[-1] a.append(b[0]) SechDic[a[0]] = { ‘ModuleName‘: a[0], ‘ButtonName‘: a[1], ‘Link‘: a[2], ‘cunt‘: a[3], } systemmongo.InsterData(SechDic[a[0]]) ActionLogFile.close() if __name__ == ‘__main__‘: Sech(ActionLog)
看一下action模版的格式
看一下插入後的集合樣子
分析nginx日誌代碼↓
#_*_ coding:utf-8 _*_ # auth: xinsir # date: 2017/10/02 # version:3.0 import systemmongo,os # 寫一個方法,判斷文件是否存在.返回布爾值 def judgment_file(FileName): if os.path.exists( FileName ): return True else: return False # 寫一個方法,把字符串切割成列表,return list def SplitStr(StrName, Format,): return StrName.split(Format) # 讀取日誌文件,獲取文件中的所有包含action的記錄,並寫入到新的log文件中 def read_file(file, new_file,): ReadPosition = 0 LastLine = 0 FileSize = 0 FileDic = {} # 打開兩個文件,一個是日誌文件,一個是臨時文件,把日誌文件進行更改後,以字典的格式序列化到日誌文件中 with open(file, ‘r‘) as log_file, open(new_file, ‘w‘) as new_log_file: # 查看文件總長多少,寫入臨時文件 FileSizeNew = os.path.getsize(file) log_file.seek(ReadPosition) if FileSize < FileSizeNew: for (num, line) in enumerate(log_file): if ‘.action‘ in line.strip(): new_line = line.strip().split(sep=‘\" \"‘) ListFirstValue = SplitStr(new_line[0], ‘\"‘) ListMostValue = SplitStr(new_line[-1], ‘\"‘) del new_line[0] del new_line[-1] new_line.insert(0, ListFirstValue[1]) new_line.append(ListMostValue[0]) Method = str(new_line[3]).split()[0] request = str(new_line[3]).split()[1] HttpVersion = str(new_line[3]).split()[2] if ‘?‘ in request: Uri = request.split(sep=‘?‘)[0] Query_string = request.split(sep=‘?‘)[1] else: Uri = request.split( sep=‘?‘ )[0] Query_string = ‘‘ if ‘.action‘ in Uri: # if LogFileStatus : FileDic[num + 1 + LastLine] = { ‘remote_addr‘: new_line[0], ‘host‘: new_line[1], ‘time_local‘: new_line[2], ‘request‘: request, ‘uri‘:Uri, ‘query_string‘:Query_string, ‘eethod‘: Method, ‘HttpVersion‘: HttpVersion, ‘body_bytes_sent‘: new_line[4], ‘http_referer‘: new_line[5], ‘http_user_agent‘: new_line[6], ‘http_x_forwarded_for‘: new_line[7], ‘server_addr‘: new_line[8], ‘status‘: new_line[9], ‘request_time‘: new_line[10], } else: print(‘靜態請求不做記錄!‘) continue IsNot = systemmongo.SechMongo( ‘http://‘ + FileDic[num + 1 + LastLine][‘host‘] + FileDic[num + 1 + LastLine][‘uri‘]) if IsNot: systemmongo.Update( ‘http://‘ + FileDic[num + 1 + LastLine][‘host‘] + FileDic[num + 1 + LastLine][‘uri‘]) print(‘更新記錄成功:‘‘http://‘ + FileDic[num + 1 + LastLine][‘host‘] + FileDic[num + 1 + LastLine][‘uri‘]) else: print(‘action請求不存在!不做記錄!‘) else: print(‘靜態請求不做處理!‘) else: print(‘日誌文件沒有發生改變!‘) new_log_file.write(str(FileDic)) log_file.close() new_log_file.close() if __name__ == ‘__main__‘: LOGPATH_new = ‘../nginxlog/b.txt‘ for fpathe, dirs, fs in os.walk(‘E:\python工程\jlj-nginx-log-web\jlj-nginx-log-web\\nginxlog\log‘): #循環目錄下的所有日誌文件 for f in fs: LOGPATH = os.path.join(fpathe, f) read_file(LOGPATH, LOGPATH_new)
配合linux的crontab任務,每天淩晨把生產環境的nginx日誌scp到線下,這裏特別要說明,因為我們的nginx訪問量很大,大的時候在線連接數能達到3000+,可想而知一天的nginx日誌也要有八九百兆,之前小編寫的代碼是一次性打開文件分別循環日誌的每一行,但是這樣會把機器的內存撐爆,所以現在是按照年月日的格式把nginx的日誌進行了切割。
看一下nginx的日誌切割
[[email protected] ~]# cat /etc/nginx/sbin/cut_log_hour.sh #!/bin/bash #nginx 日誌路徑 log_dir="/Disk/log/nginx" #當前時間 2017/09/28/15 date_dir=`date +%Y/%m/%d/%H` #創建時間目錄 /bin/mkdir -p ${log_dir}/${date_dir} > /dev/null 2>&1 # 把當前日誌移動到對應的目錄下,並且重命名 /bin/mv ${log_dir}/access.log ${log_dir}/${date_dir}/access.log # 重新生成一個日誌文件 kill -USR1 `cat /var/run/nginx.pid`
在看以下nginx的日誌記錄格式,每一個關鍵詞都用雙引號進行了分割,這樣有助於我們後臺進行日誌分析
log_format main ‘"$remote_addr" "$host" "$time_local" "$request" "$body_bytes_sent" "$http_referer" "$http_user_agent" "$http_x_forwarded_for" "$server_addr" "$status" "$request_time"‘;
小編也是初次寫代碼,如果有不對和思路淩亂的地方,還請大家指導,環境大家在評論區進行評論,也歡迎大家加我QQ同學習。
QQ:894747821
本文出自 “學習改變命運” 博客,請務必保留此出處http://xinsir.blog.51cto.com/5038915/1970198
Python統計web應用的每個連接使用情況