Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to tail and download log files from web UI. #2258

Merged
merged 1 commit into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions webapp/src/Controller/API/AbstractRestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,11 @@ protected function listActionHelper(Request $request): array
/**
* Send a binary file response, sending a 304 if it did not modify since last requested.
*/
public static function sendBinaryFileResponse(Request $request, string $fileName): BinaryFileResponse
{
public static function sendBinaryFileResponse(
Request $request,
string $fileName,
bool $download = false
): BinaryFileResponse {
// Note: we set auto-etag to true to automatically send the ETag based on the file contents.
// ETags can be used to determine whether the file changed and if it didn't change, the response will
// be a 304 Not Modified.
Expand All @@ -296,6 +299,9 @@ public static function sendBinaryFileResponse(Request $request, string $fileName
$contentType = 'image/svg+xml';
}
$response->headers->set('Content-Type', $contentType);
if ($download) {
$response->headers->set('Content-Disposition', 'attachment');
}

// Check if we need to send a 304 Not Modified and if so, send it.
// This is done both on the
Expand Down
41 changes: 38 additions & 3 deletions webapp/src/Controller/Jury/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

namespace App\Controller\Jury;

use App\Controller\API\AbstractRestController;
use App\Entity\Configuration;
use App\Service\CheckConfigService;
use App\Service\ConfigurationService;
use App\Service\DOMJudgeService;
use App\Service\EventLogService;
use App\Utils\Utils;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -127,13 +130,45 @@ public function checkAction(
): Response {
$results = $this->checkConfigService->runAll();
$stopwatch = $this->checkConfigService->getStopwatch();
$logFiles = glob($logsDir . '/*.log');
$logFilesWithSize = [];
foreach ($logFiles as $logFile) {
$logFilesWithSize[str_replace($logsDir . '/', '', $logFile)] = Utils::printsize(filesize($logFile));
}
return $this->render('jury/config_check.html.twig', [
'results' => $results,
'stopwatch' => $stopwatch,
'dir' => [
'project' => dirname($projectDir),
'log' => $logsDir,
],
'project' => dirname($projectDir),
'log' => $logsDir,
],
'logFilesWithSize' => $logFilesWithSize,
]);
}

#[Route(path: '/tail-log/{logFile<[a-z0-9-]+\.log>}', name: 'jury_tail_log')]
public function tailLogAction(
string $logFile,
#[Autowire('%kernel.logs_dir%')]
string $logsDir
): Response {
$fullFile = "$logsDir/$logFile";
$command = sprintf('tail -n200 %s', escapeshellarg($fullFile));
exec($command, $lines);
return $this->render('jury/tail_log.html.twig', [
'logFile' => $logFile,
'contents' => implode("\n", $lines),
]);
}

#[Route(path: '/download-log/{logFile<[a-z0-9-]+\.log>}', name: 'jury_download_log')]
public function downloadLogAction(
Request $request,
string $logFile,
#[Autowire('%kernel.logs_dir%')]
string $logsDir
): BinaryFileResponse {
$fullFile = "$logsDir/$logFile";
return AbstractRestController::sendBinaryFileResponse($request, $fullFile, true);
}
}
33 changes: 32 additions & 1 deletion webapp/templates/jury/config_check.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<div class="card m-3 bg-light">
<div class="card-body">
<h5 class="card-title">Installation locations</h5>
<table>
<table class="w-100">
<tr><td>Base url (use in submit client):</td><td><kbd>{{ url('root') }}</kbd></td></tr>
<tr><td>API url (use in <kbd>restapi.secret</kbd>):</td><td><kbd>{{ url('current_api_root') | trim('/', 'right') }}</kbd></td></tr>
<tr><td colspan="2">&nbsp;</td></tr>
Expand All @@ -36,6 +36,37 @@
<tr><td>DOMjudge console binary:</td><td><kbd>{{ dir.project }}/webapp/bin/console</kbd></td></tr>
<tr><td>Log directory:</td><td><kbd>{{ dir.log }}</kbd></td></tr>
</table>

{% if logFilesWithSize is not empty %}
<h5 class="card-title mt-3">Log files</h5>
<table class="w-100">
<thead>
<tr>
<th>File</th>
<th>Size</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for logFile, size in logFilesWithSize %}
<tr>
<td><kbd>{{ logFile }}</kbd></td>
<td>{{ size }}</td>
<td>
<a href="{{ path('jury_tail_log', {'logFile': logFile}) }}" class="btn btn-outline-secondary btn-sm">
<i class="fas fa-terminal"></i>
Get last 200 lines
</a>
<a href="{{ path('jury_download_log', {'logFile': logFile}) }}" class="btn btn-outline-secondary btn-sm">
<i class="fas fa-download"></i>
Download
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>

Expand Down
9 changes: 9 additions & 0 deletions webapp/templates/jury/tail_log.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'jury/base.html.twig' %}

{% block title %}Last 200 lines of {{ logFile }} - {{ parent() }}{% endblock %}

{% block content %}
<h1>Last 200 lines of <kbd>{{ logFile }}</kbd></h1>
<pre class="output_text">{{ contents }}</pre>
{% endblock %}

Loading