如何在不刷新的情况下在网页上显示更新日志文件的最后n行



我创建了一个Python应用程序,它在UNIX中模拟tail-f命令,以显示日志文件的最后10个日志,目前我的代码检测日志文件中的更改,并通过wobsockets向客户端发送更新,并在不刷新的情况下显示在网页上。

以下是的代码

  1. 当我最初运行服务器和客户端时,它会在网页上显示日志文件的最后10行
  2. 当我更新日志文件时,第11行也会显示,如果我更新了n行,它会显示n行以及最初显示的前10行

只是为了描述,我希望我的最终输出是什么样子,比如说我想显示日志文件的最后5行

我的日志文件看起来像这个

1
2
3
4
5
6
7

在运行服务器和客户端时,我的网页显示这个(日志页面的最后5行(

3
4
5
6
7

所以当我用新条目更新日志文件时,让我们说-->8,我的最终输出应该是

4
5
6
7
8

这应该在不刷新页面的情况下发生,但现在它被打印为

3
4
5
6
7
8

这是我的server.py文件

import time
import os.path
import asyncio
import logging
from collections import deque
import websockets
from ansi2html import Ansi2HTMLConverter
NUM_LINES = 10
HEARTBEAT_INTERVAL = 15
conv = Ansi2HTMLConverter(inline=True)
async def view_log(websocket, path):
try:
file_path='log.log'
tail=True
i=0
with open(file_path) as f:
content = ''.join(deque(f, NUM_LINES))
content = conv.convert(content, full=False)
await websocket.send(content)
if tail:
last_heartbeat = time.time()
while True:
content = f.read()
if content:
i+=1
content = conv.convert(content, full=False)
await websocket.send(content)
else:
await asyncio.sleep(1)
# heartbeat
#print(last_heartbeat)
if time.time() - last_heartbeat > HEARTBEAT_INTERVAL:
try:
await websocket.send('ping')
pong = await asyncio.wait_for(websocket.recv(), 5)
if pong != 'pong':
raise Exception()
except Exception:
raise Exception('Ping error')
else:
last_heartbeat = time.time()
else:
await websocket.close()
except ValueError as e:
try:
await websocket.send(e)
await websocket.close()
except Exception:
pass
log_close(websocket, path, e)
except Exception as e:
log_close(websocket, path, e)
else:
log_close(websocket, path)

def log_close(websocket, path, exception=None):
message = 'Closed, remote={}, path={}'.format(websocket.remote_address, path)
if exception is not None:
message += ', exception={}'.format(exception)
logging.info(message)

def main():
parser = argparse.ArgumentParser()
parser.add_argument('--host', default='127.0.0.1')
parser.add_argument('--port', type=int, default=8765)
args = parser.parse_args()
start_server = websockets.serve(view_log, args.host, args.port)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

if __name__ == '__main__':
main()

这是我的demo.html文件,其中显示O/p

<html>
<head>
<title>Logviewer Demo</title>
</head>
<body>
<pre id="logs"></pre>
<script>
let ws = new WebSocket('ws://localhost:8765')
ws.onmessage = (event) => {
if (event.data === 'ping') {
ws.send('pong')
return
}
document.getElementById('logs').innerHTML += event.data
}
</script>
</body>
</html>

要运行此操作,您需要在命令行中执行以下步骤

  1. python server.py --host 127.0.0.1 --port 8765
  2. python -m http.server
  3. 在网络浏览器http://localhost:8000/demo.html上打开此

这可以在前端解决。为此,您可以创建一个函数,该函数采取以下步骤:

  1. 获取元素引用
  2. 创建一个变量,将其分配给我们的元素当前文本,并将我们的新日志文本添加到其中,中间有一行新行
  3. 将新字符串拆分为一个数组,在新行处进行拆分('\n'(
  4. 拼接出不是最后5个的所有阵列元素
  5. 将数组重新连接成一个字符串,并用新行分隔每个字符串
  6. 将我们的新字符串分配给元素innerText

函数如下所示:

function updateLog(newLog){
let elem = document.getElementById('logs')
let newText = elem.innerText + 'n' + newLog
newText = newText.split('n')
newText.splice(0, newText.length-5)
newText = newText.join('n')
elem.innerText = newText
}

将该功能放入<script>部分

删除这一行,因为我们正在用我们的函数调用替换它

document.getElementById('logs').innerHTML += event.data

然后使用新功能:

updateLog(event.data)

最新更新