推薦項目:https://github.com/olajowon/loggrove
一、主題:實時展示服務器端動態生成的日志文件
二、流程:
1. 客戶端瀏覽器與服務器建立websocket 鏈接,服務器掛起保存鏈接實例,等待新內容觸發返回動作
2. 日志服務器腳本循環去發現新內容,發現新行向 tornado等待API POST 發送新內容
3. tornado 處理器接收到新內容, 通過 websocket 向保存的客戶端鏈接返回新行
4. 客戶端瀏覽器接收到新內容,修飾,展示
三、代碼:
1. tornado服務器url路由、基本頁面handler 及 html:
#模塊路徑根據自身項目而定 (r'/logs/index/', 'apps.logs.handler.IndexHandler'), (r'/logs/newlinesforcallbacker/', 'apps.logs.handler.WriteNewLinesHandler'), (r'/logs/newlinesforserver/', 'apps.logs.handler.ReceiveNewLinesHandler'),
class IndexHandler(BaseHandler): ''' 主頁 ''' def get(self, *args, **kwargs): self.render('logs/index.html')
<div align="center"> <h2>this logs monitor</h2> <div style="width: 70%" id="main"> <!-- 行展示 --> </div> </div>
2. 服務器端websocket handler (WriteNewLinesHandler) 、 保存刪除鏈接處理類 及客戶端websocket請求 js
class ProStatus(object): ''' 處理類 ''' w_register = [] def register(self, callbacker): ''' 記錄客戶端連接實例 ''' self.w_register.append(callbacker) def unregister(self, callbacker): ''' 刪除客戶端連接實例 ''' self.w_register.remove(callbacker) def makelines(self, lines): ''' 處理接受的行內容 ''' pass def trigger(self, line): ''' 向所有被記錄客戶端發送最新內容 ''' pass class WriteNewLinesHandler(tornado.websocket.WebSocketHandler): ''' 接受websocket鏈接,保存鏈接實例 ''' def check_origin(self, origin): #針對websocket處理類重寫同源檢查的方法 return True def open(self): ''' 處理新的連接 ''' ProStatus().register(self) def on_close(self): ProStatus().unregister(self) #刪除客戶端連接 def on_message(self, message): pass
$(function(){ function requestText(){ host = "ws://" + location.hostname + ":" + location.port + "/logs/newlinesforcallbacker/" websocket = new WebSocket(host) websocket.onopen = function(evt){} // 建立連接 websocket.onmessage = function(evt){ // 獲取服務器返回的信息 data = $.parseJSON(evt.data) $("#main").append(data+"</br>") //寫入頁面 } websocket.onerror = function(evt){} } requestText() })
3. tornado 等待腳本提交新內容處理handler(ReceiveNewLinesHandler)、 向掛起客戶端發送新內容函數 及 遍歷日志提交新內容腳本
class ProStatus(object): ''' 處理類 ''' w_register = [] def register(self, callbacker): ''' 記錄客戶端連接實例 ''' pass def unregister(self, callbacker): ''' 刪除客戶端連接實例 ''' pass def makelines(self, lines): ''' 處理接受的行內容 ''' for line in lines: self.trigger(line) def trigger(self, line): ''' 向所有被記錄客戶端發送最新內容 ''' for callabler in self.w_register: callabler.write_message(json.dumps(line)) class ReceiveNewLinesHandler(BaseHandler): ''' 接受服務器端腳本提交的最新行內容 ''' def post(self, *args, **kwargs): linesdata = self.get_argument('lines', '') #print type(json.loads(linesdata)) ProStatus().makelines(json.loads(linesdata))
#-*-coding:utf-8-*- __author__ = 'zhouwang' import time import urllib import urllib2 import json p = 0 while True: f = open('logs.txt', 'r+') f.seek(p, 0) #偏移到上次結束位置 lines = f.readlines() if lines: #對行內容操作, 向服務器發送最新行內容 data = urllib.urlencode({'lines':json.dumps(lines)}) url = 'http://localhost:8800/logs/newlinesforserver/' req = urllib2.Request(url, data) res_data = urllib2.urlopen(req) #print res_data.read() #獲取當前位置,作為偏移值 p = f.tell() f.close() time.sleep(1)
ps: 遍歷大日志文件,及過濾行內容請參考:http://www.cnblogs.com/wowoo1121/p/5381971.html
開源日志項目:loggrove https://github.com/olajowon/loggrove