python tornado websocket 实时日志展示
推荐项目: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