Skip to content
This repository has been archived by the owner on Aug 9, 2024. It is now read-only.

Commit

Permalink
improve plugin log viewer
Browse files Browse the repository at this point in the history
- move start server to dedicated function within `webapp.py`
- get log stream via new function
- update logs on a 5 second interval
- add switch to disable auto update of logs
  • Loading branch information
ReenigneArcher committed Feb 24, 2023
1 parent 1d28959 commit 2009017
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jobs:
!**/Plugger.bundle/Dockerfile
!**/Plugger.bundle/docs
!**/Plugger.bundle/scripts
!**/Plugger.bundle/tests
- name: Package Release
shell: bash
Expand All @@ -113,6 +114,7 @@ jobs:
"-xr!Plugger.bundle/Dockerfile" \
"-xr!Plugger.bundle/docs" \
"-xr!Plugger.bundle/scripts" \
"-xr!Plugger.bundle/tests" \
a "./Plugger.bundle.zip" "Plugger.bundle"
mkdir artifacts
Expand Down
22 changes: 2 additions & 20 deletions Contents/Code/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
# -*- coding: utf-8 -*-

# standard imports
import sys
from threading import Thread

# plex debugging
try:
import plexhints # noqa: F401
Expand All @@ -21,7 +17,7 @@

# local imports
from default_prefs import default_prefs
from webapp import app
from webapp import start_server


def ValidatePrefs():
Expand All @@ -46,7 +42,6 @@ def ValidatePrefs():
>>> ValidatePrefs()
...
"""
# todo - validate username and password
error_message = '' # start with a blank error message

for key in default_prefs:
Expand Down Expand Up @@ -108,22 +103,9 @@ def Start():
if prefs_valid.header == 'Error':
Log.Warn('plug-in preferences are not valid.')

start_server() # start the web server if it is not running
Log.Debug('plug-in started.')

# use threading to start the flask app... or else web server seems to be killed after a couple of minutes
flask_thread = Thread(
target=app.run,
kwargs=dict(
host=Prefs['str_http_host'],
port=Prefs['int_http_port'],
debug=False,
use_reloader=False # reloader doesn't work when running in a separate thread
)
)

# start flask application
flask_thread.start()


@handler(prefix='/applications/plugger', name='Plugger', thumb='attribution.png')
def main():
Expand Down
61 changes: 58 additions & 3 deletions Contents/Code/webapp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# standard imports
import logging
import os
from threading import Thread

# plex debugging
try:
Expand All @@ -14,8 +15,8 @@

# lib imports
import flask
from flask import Flask
from flask import render_template, send_from_directory
from flask import Flask, Response
from flask import render_template, request, send_from_directory
from flask_babel import Babel

# local imports
Expand Down Expand Up @@ -99,6 +100,28 @@ def get_locale():
return Prefs['enum_locale']


def start_server():
# use threading to start the flask app... or else web server seems to be killed after a couple of minutes
flask_thread = Thread(
target=app.run,
kwargs=dict(
host=Prefs['str_http_host'],
port=Prefs['int_http_port'],
debug=False,
use_reloader=False # reloader doesn't work when running in a separate thread
)
)

# start flask application
flask_thread.start()


def stop_server():
# stop flask server
# todo - this doesn't work
request.environ.get('werkzeug.server.shutdown')


@app.route('/')
@app.route('/home')
def home():
Expand Down Expand Up @@ -184,7 +207,39 @@ def logs(plugin):
--------
>>> logs(plugin='dev.lizardbyte.plugger')
"""
return render_template('logs.html', title='Logs', plugin_identifier=plugin)


@app.route('/log_stream/', defaults={'plugin': bundle_identifier})
@app.route("/log_stream/<path:plugin>", methods=["GET"])
def log_stream(plugin):
# type: (str) -> Response
"""
Serve the plugin logs in plain text.
Collect and format the logs for the specified plugin.
Parameters
----------
plugin : str
The reverse domain name of the plugin, e.g. `dev.lizardbyte.plugger`.
Returns
-------
Response
The text of the log files.
Notes
-----
The following routes trigger this function.
`/log_stream/`
`/log_stream/<plugin name>`
Examples
--------
>>> log_stream(plugin='dev.lizardbyte.plugger')
"""
base_log_file = '%s.log' % plugin
combined_log = ''

Expand All @@ -202,7 +257,7 @@ def logs(plugin):
combined_log += str(Core.storage.load(filename=log_file, binary=False))
count += -1

return render_template('logs.html', title='Logs', logs=combined_log)
return Response(combined_log, mimetype="text/plain", content_type="text/event-stream")


@app.route('/status')
Expand Down
1 change: 1 addition & 0 deletions Contents/Resources/web/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<!-- The page template -->
{% block content %}{% endblock %}
</main>
{% block scripts %}{% endblock %}
</body>

</html>
69 changes: 61 additions & 8 deletions Contents/Resources/web/templates/logs.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,68 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<div class="row">
<h2>Logging will appear here:</h2>
<div class="logging_window">
<pre id="logs">{{ logs }}</pre>
</div>
</div>
<div class="row text-white">
{# Auto refresh toggle #}
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switch_auto_refresh" checked>
<label class="form-check-label" for="switch_auto_refresh">{{ _('Auto refresh') }}</label>
</div>
<h2>{{ _('Plugin Logs:') }}</h2>
<div id="logging_window">
<pre id="logs"></pre>
<button id="copy-btn" type="button" class="btn btn-outline-light rounded-0 position-absolute top-0 end-0 mt-2 me-2" data-clipboard-target="#logs">
<i class="fa-solid fa-fw fa-copy"></i>
</button>
</div>
</div>
</div>
{% endblock content %}

{% block scripts %}
<script type="text/javascript" src="{{ url_for('static', filename='node_modules/clipboard/dist/clipboard.min.js') }}"></script>
<script>
new ClipboardJS('#copy-btn');
</script>

<script>
// this will run every 5 seconds to update the logs
updateLogs = () => {
$.ajax({
url: "/log_stream/{{ plugin_identifier }}",
type: "GET",
success: function (data) {
let log_container = document.getElementById("logs")
log_container.innerHTML = data
}
})
}

// update the logs immediately
updateLogs()

// then setup update timer to update every 5 seconds
const updateIntervalPeriod = 5000
var updateInterval
// setInterval(updateLogs, updateIntervalPeriod)

// add event listeners to the auto-refresh toggle switch
const switchAutoRefresh = document.getElementById("switch_auto_refresh");
switchAutoRefresh.addEventListener("change", () => {
toggleAutoRefresh()
})

// function to toggle the auto-refresh switch
toggleAutoRefresh = () => {
if (switchAutoRefresh.checked) {
// turn on auto-refresh
updateInterval = setInterval(updateLogs, updateIntervalPeriod)
} else {
// turn off auto-refresh
clearInterval(updateInterval);
}
}

// run the toggle function to set the initial state
toggleAutoRefresh()
</script>
{% endblock scripts %}
10 changes: 9 additions & 1 deletion Contents/Strings/plugger.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Plugger v0\n"
"Report-Msgid-Bugs-To: github.com/plugger\n"
"POT-Creation-Date: 2023-02-24 11:35-0500\n"
"POT-Creation-Date: 2023-02-24 14:43-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand All @@ -17,6 +17,14 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"

#: Contents/Resources/web/templates/logs.html:8
msgid "Auto refresh"
msgstr ""

#: Contents/Resources/web/templates/logs.html:10
msgid "Plugin Logs:"
msgstr ""

#: Contents/Resources/web/templates/navbar.html:25
msgid "Donate"
msgstr ""
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@fontsource/open-sans": "4.5.13",
"@fortawesome/fontawesome-free": "6.2.0",
"bootstrap": "5.2.2",
"jquery": "3.6.1"
"clipboard": "2.0.11",
"jquery": "3.6.3"
}
}
3 changes: 0 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
import os
import sys

# lib imports
import pytest

# add Contents directory to the system path
if os.path.isdir('Contents'):
sys.path.append('Contents')
Expand Down

0 comments on commit 2009017

Please sign in to comment.