Display the contents of a log file as it is updated Display the contents of a log file as it is updated flask flask

Display the contents of a log file as it is updated


Use a Flask view to continuously read from the file forever and stream the response. Use JavaScript to read from the stream and update the page. This example sends the entire file, you may want to truncate that at some point to save bandwidth and memory. This example sleeps between reads to reduce cpu load from the endless loop and allow other threads more active time.

from time import sleepfrom flask import Flask, render_templateapp = Flask(__name__)@app.route('/')def index():    return render_template('index.html')@app.route('/stream')def stream():    def generate():        with open('job.log') as f:            while True:                yield f.read()                sleep(1)    return app.response_class(generate(), mimetype='text/plain')app.run()
<pre id="output"></pre><script>    var output = document.getElementById('output');    var xhr = new XMLHttpRequest();    xhr.open('GET', '{{ url_for('stream') }}');    xhr.send();    setInterval(function() {        output.textContent = xhr.responseText;    }, 1000);</script>

This is almost the same as this answer, which describes how to stream and parse messages, although reading from an external file forever was novel enough to be it's own answer. The code here is simpler because we don't care about parsing messages or ending the stream, just tailing the file forever.


I am using frontail package from npm.

npm i frontail -gfrontail /var/log/syslog

visit http://127.0.0.1:9001 to view logs

Source: https://github.com/mthenw/frontail

This may not be the exact answer for the question(to embed an html page), but it solves the problem of many users who are looking specifically only for

Display the contents of a log file as it is updated


For me @davidism solution (accepted answer) worked only on Firefox. It didnt work in Chrome, Brave, Vivaldi. Maybe there was some kind of de-sync in backend and frontend loops? I dont know.

Anyway i used far simpler solution, without loop on the backend and javascript loop on frontend. Maybe it's "uglier" and may cause trouble for some very long logs, but at least it works on every browser i use.

@app.route('/stream')def stream():    with open("job.log", "r") as f:            content = f.read()    # as you see, file is loaded only once, no loop here, (loop is on frontend side)    return app.response_class(content, mimetype='text/plain')
<!DOCTYPE html><html>    <head>        <!-- page auto-refresh every 10 seconds -->        <meta http-equiv="refresh" content="10">        <title>Some title</title>    </head>    <body>        <h1>Log file ...</h1>        <script>           // function for adjusting iframe height to log size            function resizeIframe(obj) {              obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';            }          </script>        <!-- iframe pulls whole file -->        <iframe src="{{ url_for('stream') }}" frameborder="0" style="overflow:hidden;width:100%" width="100%" frameborder="0" scrolling="no" onload="resizeIframe(this)"></iframe>    </body></html>

As you see the only javascript code is used to adjust iframe height to current text size.