diagnostics, help: Link to diagnostics page logs in 500 error page

Closes: #2414.

- Remove separate implementation for showing logs in help page.

- Add link to the page in diagnostics app so that FreedomBox logs can more
easily be discovered by users.

Tests:

- Raise an exception in the common error middleware to cause a 500 internal
server error. Run FreedomBox service with the --develop option and notice that
500 error page is served. There, the link to logs page works. It shows the logs
for Diagnostics app.

- Diagnostics page description is update. Link to logs page works.

- Diagnostics page shows logs for plinth.service and freedombox-develop.service.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
This commit is contained in:
Sunil Mohan Adapa 2025-09-11 13:04:41 -07:00 committed by Veiko Aasa
parent e82d959c85
commit 5a55b59939
No known key found for this signature in database
GPG Key ID: 478539CAE680674E
7 changed files with 20 additions and 106 deletions

View File

@ -11,24 +11,31 @@ import threading
from copy import deepcopy from copy import deepcopy
import psutil import psutil
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext_noop from django.utils.translation import gettext_noop
from plinth import app as app_module from plinth import app as app_module
from plinth import daemon, glib, kvstore, menu from plinth import cfg, glib, kvstore, menu
from plinth import operation as operation_module from plinth import operation as operation_module
from plinth.daemon import RelatedDaemon, diagnose_port_listening
from plinth.diagnostic_check import (CheckJSONDecoder, CheckJSONEncoder, from plinth.diagnostic_check import (CheckJSONDecoder, CheckJSONEncoder,
DiagnosticCheck, Result) DiagnosticCheck, Result)
from plinth.modules.apache.components import diagnose_url_on_all from plinth.modules.apache.components import diagnose_url_on_all
from plinth.modules.backups.components import BackupRestore from plinth.modules.backups.components import BackupRestore
from plinth.setup import run_repair_on_app from plinth.setup import run_repair_on_app
from plinth.utils import format_lazy
from . import manifest from . import manifest
_description = [ _description = [
_('The system diagnostic test will run a number of checks on your ' _('The system diagnostic test will run a number of checks on your '
'system to confirm that applications and services are working as ' 'system to confirm that applications and services are working as '
'expected.') 'expected.'),
format_lazy(
_('This app also shows the <a href="{logs_url}">logs</a> for '
'{box_name} services.'), box_name=_(cfg.box_name),
logs_url=reverse_lazy('logs', args=['diagnostics']))
] ]
logger = logging.Logger(__name__) logger = logging.Logger(__name__)
@ -61,6 +68,14 @@ class DiagnosticsApp(app_module.App):
order=30) order=30)
self.add(menu_item) self.add(menu_item)
# Add FreedomBox daemons to show logs for them.
daemon = RelatedDaemon('related-daemon-plinth', 'plinth')
self.add(daemon)
daemon = RelatedDaemon('related-daemon-freedombox-privileged',
'freedombox-privileged')
self.add(daemon)
backup_restore = BackupRestore('backup-restore-diagnostics', backup_restore = BackupRestore('backup-restore-diagnostics',
**manifest.backup) **manifest.backup)
self.add(backup_restore) self.add(backup_restore)
@ -82,7 +97,7 @@ class DiagnosticsApp(app_module.App):
def diagnose(self) -> list[DiagnosticCheck]: def diagnose(self) -> list[DiagnosticCheck]:
"""Run diagnostics and return the results.""" """Run diagnostics and return the results."""
results = super().diagnose() results = super().diagnose()
results.append(daemon.diagnose_port_listening(8000, 'tcp4')) results.append(diagnose_port_listening(8000, 'tcp4'))
results.extend( results.extend(
diagnose_url_on_all('http://{host}/plinth/', diagnose_url_on_all('http://{host}/plinth/',
check_certificate=False)) check_certificate=False))

View File

@ -1,14 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Actions for help module."""
import subprocess
from plinth.actions import privileged
@privileged
def get_logs() -> str:
"""Get latest FreedomBox logs."""
command = ['journalctl', '--no-pager', '--lines=100', '--unit=plinth']
process = subprocess.run(command, check=True, stdout=subprocess.PIPE)
return process.stdout.decode()

View File

@ -1,38 +0,0 @@
{% extends 'help_base.html' %}
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
{% load i18n %}
{% block content %}
<h2>{% trans "Status Log" %}</h2>
<p>
{% blocktrans trimmed %}
These are the last {{ num_lines }} lines of the status log for this web
interface. If you want to report a bug, please use the <a
href="https://salsa.debian.org/freedombox-team/freedombox/issues">bug
tracker</a> and attach this status log to the bug report.
{% endblocktrans %}
</p>
<div class="alert alert-warning d-flex align-items-center">
<div class="me-2">
<span class="fa fa-exclamation-triangle" aria-hidden="true"></span>
<span class="visually-hidden">{% trans "Caution:" %}</span>
</div>
<div>
{% blocktrans trimmed %}
Please remove any personal information from the log before submitting
the bug report.
{% endblocktrans %}
</div>
</div>
<p>
<pre class="status-log">{{ data }}</pre>
</p>
{% endblock %}

View File

@ -1,38 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Functional, browser based tests for help app.
"""
import pytest
from plinth.tests import functional
pytestmark = [pytest.mark.system, pytest.mark.essential, pytest.mark.help]
# TODO Scenario: Visit the wiki
# TODO Scenario: Visit the mailing list
# TODO Scenario: Visit the IRC channel
# TODO Scenario: View the manual
# TODO Scenario: View the about page
@pytest.fixture(scope='module', autouse=True)
def fixture_background(session_browser):
"""Login."""
functional.login(session_browser)
def test_view_status_logs(session_browser):
"""Test viewing the status logs."""
_go_to_status_logs(session_browser)
assert _are_status_logs_shown(session_browser)
def _go_to_status_logs(browser):
functional.visit(browser, '/plinth/help/status-log/')
def _are_status_logs_shown(browser):
status_log = browser.find_by_css('.status-log').first.text
return ('-- No entries --' in status_log
or status_log.strip().splitlines())

View File

@ -25,6 +25,4 @@ urlpatterns = [
non_admin_view(views.manual), name='manual-page'), non_admin_view(views.manual), name='manual-page'),
re_path(r'^help/manual-download/$', non_admin_view(views.download_manual), re_path(r'^help/manual-download/$', non_admin_view(views.download_manual),
name='download-manual'), name='download-manual'),
re_path(r'^help/status-log/$', non_admin_view(views.status_log),
name='status-log'),
] ]

View File

@ -19,8 +19,6 @@ from django.utils.translation import gettext as _
from plinth import __version__, cfg, menu from plinth import __version__, cfg, menu
from plinth.modules.upgrades import views as upgrades_views from plinth.modules.upgrades import views as upgrades_views
from . import privileged
def index(request): def index(request):
"""Serve the index page""" """Serve the index page"""
@ -164,10 +162,3 @@ def download_manual(request):
response['Content-Encoding'] = encoding response['Content-Encoding'] = encoding
return response return response
def status_log(request):
"""Serve the last 100 lines of plinth's status log."""
logs = privileged.get_logs()
context = {'num_lines': 100, 'data': logs}
return TemplateResponse(request, 'statuslog.html', context)

View File

@ -10,13 +10,13 @@
<h2>{% trans "500" %}</h2> <h2>{% trans "500" %}</h2>
<p> <p>
{% url 'help:status-log' as status_log_url %} {% url 'logs' app_id='diagnostics' as logs_url %}
{% blocktrans trimmed %} {% blocktrans trimmed %}
This is an internal error and not something you caused or can fix. Please This is an internal error and not something you caused or can fix. Please
report the error on the <a report the error on the <a
href="https://salsa.debian.org/freedombox-team/freedombox/issues">bug href="https://salsa.debian.org/freedombox-team/freedombox/issues">bug
tracker</a> so we can fix it. Also, please attach the <a tracker</a> so we can fix it. Also, please attach the <a
href="{{ status_log_url }}">status log</a> to the bug report. href="{{ logs_url }}">logs</a> to the bug report.
{% endblocktrans %} {% endblocktrans %}
</p> </p>