稍微成型点的用WEBSOCKET实现的实时日志LOG输出

难的是还是就地用JS显示出来相关的发布进度。

还好,花了一下午实现了。

可以移植到项目中去罗。。。

websocket.py:

import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.ioloop import IOLoop
from datetime import timedelta
import time
import os
import sys
import tornado.httpserverclass WebSocketHandler(tornado.websocket.WebSocketHandler):file_content = ""filename = "test.log"def open(self):passdef update_client(self):self.write_message(self._read_file(self.filename))def on_message(self, message):print messageself.filename = message.split('-')[1]self.update_client()def on_close(self):passdef _read_file(self, filename):print filename, '================='with open(filename) as f:content = f.read()content_diff = content.replace(self.file_content, '')self.file_content = contentreturn content_diffclass IndexPageHandler(tornado.web.RequestHandler):def get(self):self.render("websockets.html")class Application(tornado.web.Application):def __init__(self):handlers = [(r'/', IndexPageHandler),(r'/ws', WebSocketHandler)]settings = dict(template_path=os.path.join(os.path.dirname(__file__), "templates"),static_path=os.path.join(os.path.dirname(__file__), "static"),debug=True)tornado.web.Application.__init__(self, handlers, **settings)if __name__ == '__main__':ws_app = Application()server = tornado.httpserver.HTTPServer(ws_app)server.listen(8888)tornado.ioloop.IOLoop.instance().start()

websocket.html:

<title>Tornado WebSockets</title><link rel="stylesheet" href="/static/uikit-2.22.0/css/uikit.min.css" />
<link rel="stylesheet" href="/static/uikit-2.22.0/css/components/progress.gradient.css"/>
<link rel="stylesheet" href="/static/css/radialindicator.css"/>
<script src="/static/js/jquery-1.11.2.js"></script>
<script src="/static/js/radialIndicator.min.js"></script>
<script src="/static/uikit-2.22.0/js/uikit.js"></script>
<script src="/static/uikit-2.22.0/js/components/sticky.min.js"></script><div id="procPer"></div>
<br>
<textarea id="logoutput" cols="100" rows="30" placeholder="日志输出" style="background:#000; color:#FFF" >...</textarea>
<br>
<a href="javascript:void(0);" onClick="wsFunc('stop', 'DEMO')"><span id="actionSpn"  class="uk-button">停止刷新</span></a>
<script>function GetRequest() {var url = location.search;var theRequest = new Object();if (url.indexOf("?") != -1) {var str = url.substr(1);strs = str.split("&");for(var i = 0; i < strs.length; i ++) {theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);}}return theRequest;}
var Request = new Object();
Request = GetRequest();
console.log(Request);
var dev_version = Request['dev_version'];
console.log(dev_version);wsFunc("refresh", dev_version);function wsFunc(msg, dev_version) {var messageContainer = document.getElementById("logoutput");var percentContainer = document.getElementById("procPer");if ("WebSocket" in window) {var ws = new WebSocket("ws://localhost:8888/ws");ws.onopen = function() {};ws.onmessage = function (evt) {messageContainer.innerHTML += evt.data;var d = messageContainer.scrollHeight;messageContainer.scrollTop = d;var pattern = /progress/gi;var ans = messageContainer.innerHTML.match(/\w+.\w+,\sdeploy\sprogress\s\d+/g);var dic = new Array();for (item in ans){dic_key = ans[item].split(',')[0];dic_value = ans[item].split(',')[1].split(" ")[3];dic[dic_key] = dic_value;}for (key in dic) {if(document.getElementById(key + "label") == undefined){var span=document.createElement('span');span.setAttribute("id", key + "label");percentContainer.appendChild(span);document.getElementById(key + "label").innerHTML = key}if(document.getElementById(key) == undefined){var span=document.createElement('span');span.setAttribute("id", key);percentContainer.appendChild(span);//document.getElementById(key).innerHTML =dic[key];
                        $(span).radialIndicator({barColor: {10: '#0000FF',70: '#0000FF',90: '#0000FF',100: '#33CC33'},radius: 25,barWidth: 3,initValue: dic[key],roundCorner : true,percentage: true});radialObj =$(span).data('radialIndicator');}radialObj.animate(dic[key]);console.log(key, dic[key]);}};ws.onclose = function() {};console.log(msg);if (msg == "refresh") {sh=setInterval(function(){ws.send(msg+"-"+dev_version, function(){})},2000);} else {clearInterval(sh);document.getElementById("actionSpn").innerText = 'OutPut';}} else {messageContainer.innerHTML += "此浏览器不支持websocket!";}}</script>

样子:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET6之MiniAPI(四):配置

配置文件&#xff0c;是一个每个应用服务程序常用的功能&#xff0c;从原来的终端应用时代&#xff0c;到现在的元宇宙时代&#xff0c;配置都是很悠然自得的存在。asp.net core提供了强大的配置文件访问机制&#xff0c;不管是MVC API还是MiniAPI&#xff0c;使用方式都是相同…

.NET 6新特性试用 | PeriodicTimer

前言在.NET中&#xff0c;已经存在了5个Timer类&#xff1a;System.Threading.TimerSystem.Timers.TimerSystem.Web.UI.TimerSystem.Windows.Forms.TimerSystem.Windows.Threading.DispatcherTimer不管以前这样设计的原因&#xff0c;现在.NET 6又为我们增加了一个新Timer&…

ChatForFun 公众号使用说明

使用方法 2016-07-16 DennisMi ChatForFun1&#xff0c;发送 #1 实现登陆&#xff0c;或者退出登陆 2&#xff0c;发送 #2 实现加入聊天&#xff0c;和退出聊天 3&#xff0c;聊天开始后&#xff0c;可以直接发送消息 4&#xff0c;如果需要退出登陆或者退出聊天&#xff0c;…

.NET 6新特性试用 | 总结:我最喜欢的5个特性

前言不知不觉&#xff0c;《.NET 6新特性试用》系列文章已经写了20多篇&#xff0c;而今天终于要告一段落了。如果你还没有看过&#xff0c;详细文章列表在这里&#xff1a;.NET 6新特性试用系列在这么多特性中&#xff0c;我最喜欢如下5个特性&#xff1a;1、最小Web API仅需三…

mikrotikROS系统的几种安装方法

这里简单介绍下几种ROS的安装方法,以及适用于哪些设备,这里我们先提供一个ROS6.0全系列版本的下载链接mikrotik-RouteOS-V6.0正式版下载 或者前往官方下载最新版常见的ROS硬件一般分为:X86架构(也是最常用的)mipsbe(欧米tik,部分RB系列,SXT,Groove等)mipsle(RBC系列,RB100,R…

分布式云+dubbo+zookeeper+Springmvc整合

2019独角兽企业重金招聘Python工程师标准>>> Dubbo采用全Spring配置方式&#xff0c;透明化接入应用&#xff0c;对应用没有任何API侵入&#xff0c;只需用Spring加载Dubbo的配置即可&#xff0c;Dubbo基于Spring的Schema扩展进行加载。 一&#xff1a;单机模式安装…

.Net下你不得不看的分表分库解决方案-多字段分片

介绍本期主角:ShardingCore 一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案&#xff0c;具有零依赖、零学习成本、零业务代码入侵dotnet下唯一一款全自动分表,多字段分表框架,拥有高性能,零依赖、零学习成本、零业务代码入侵,并且支持读写分离动态分表分库,同一种…

知乎高赞:看懂这个颠覆世界观的认知,远比做1000道题更有用!

▲ 点击查看知乎上曾有个提问&#xff1a;“见过世面究竟有多重要&#xff1f;”其中一个点赞过万回答让无数网友产生共鸣&#xff1a;会讲究&#xff0c;能将就&#xff0c;能享受最好的&#xff0c;也能承受最坏的。见过世面的他们自然会在人群中散发不一样的气质&#xff0c…

WebBrowser!

WebBrowser! 原文:WebBrowser!我现在先放一些基础的文章在这里&#xff0c;以后再放别的上来官方范例连接http://www.microsoft.com/china/msdn/library/langtool/vcsharp/OvervwWebBrowExp.mspxQ&A 2005年5月21日 0:14:19 Q: 新键入的地址不能在新建好的窗口里打开:A:每…

Android USB Host与HID通讯(二)

2019独角兽企业重金招聘Python工程师标准>>> 原文出处&#xff1a;http://han21912.lofter.com/post/c3919_51401d 接上一篇&#xff1a;Android USB Host与HID通讯 (一) 从上篇已经可以枚举到HID设备&#xff0c;接下来看看寻找设备的接口和通信端点&#xff0c;…

CentOS7安装PHP5.6.23

为什么80%的码农都做不了架构师&#xff1f;>>> 美国时间2014年11月13日&#xff0c;PHP开发团队&#xff0c;在「PHP 5.6.3 is available&#xff5c;PHP: Hypertext Preprocessor」上公布了PHP5.6系的最新版本「PHP 5.6.3」。 在最新的版本5.6.3不仅修改了多个Bu…

为什么接吻需要闭眼睛?

1 你用上5G了吗&#xff1f;它已经用上了▼2 戴口罩的好处又增加了▼3 原来如此...▼4 哈哈哈哈▼5 露脐装的正确打开方式&#xff08;素材源于网络&#xff0c;侵删&#xff09;▼6 火鸡面到底有多辣▼7 孩子你要完了&#xff08;素材来源网络&#xff0c;侵删&#xff0…

最近要出绩效了

上周我们公司的绩效面谈全部结束了&#xff0c;每年到这个时间点就是打绩效的时候了&#xff0c;对于职场打工人来说绩效绝对是最重要的事情之一&#xff0c;原因也很简单&#xff1a;奖金、晋升、涨薪都和它有关系。比如下面这个美团员工在脉脉上的自曝就很凄凉&#xff1a;互…

从B 树、B+ 树、B* 树谈到R 树

作者&#xff1a;July、weedge、Frankie。编程艺术室出品。 说明&#xff1a;本文从B树开始谈起&#xff0c;然后论述B树、B*树&#xff0c;最后谈到R 树。其中B树、B树及B*树部分由weedge完成&#xff0c;R 树部分由Frankie完成&#xff0c;全文最终由July统稿修订完成。 出…

纯IPv6环境App适配的坑

来源&#xff1a;伯乐在线专栏作者 - MrPeak 链接&#xff1a;http://ios.jobbole.com/86580/ 苹果从2016年6月1号开始&#xff0c;强制所有app必须支持纯IPv6的网络环境。这项举措将对IPv6的普及起到一定的推动作用&#xff0c;也体现了Apple作为国际大厂的担当。 大部分App由…

使用Visual Studio 创建新的Web Part项目

使用Visual Studio 创建新的Web Part项目 Web Part是你将为SharePoint创建的最常见的对象之一。它是平台构建的核心基块。1. 管理员身份打开Visual Studio&#xff0c;新建空白SharePoint项目。命名WroxSPProject&#xff0c;点击确定。部署为场解决方案&#xff0c;点击完成。…

聊一聊Yarp结合Nacos完成服务发现

背景 Yarp 这个反向代理出来后&#xff0c;相信还是有不少人在关注的。在 Yarp 中&#xff0c;反向代理的配置默认也是基于配置文件的&#xff0c;也有不少大佬已经把这个配置做成了数据库配置可视化界面。仔细想了想&#xff0c;做成数据库配置&#xff0c;好像只是便于配置的…