Skip to content

Commit

Permalink
Tail admin logs to always display data
Browse files Browse the repository at this point in the history
Follow-up #4876

Thanks to Torleif Berger for it's code for Tail tackling large files in PHP http://www.geekality.net/?p=1654
  • Loading branch information
rldhont committed Nov 15, 2024
1 parent e2d6470 commit 1fbb070
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 69 deletions.
13 changes: 1 addition & 12 deletions lizmap/modules/admin/controllers/logs.classic.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,7 @@ public function index()
$detailNumber = $dao->countBy($conditions);

// Get last error log
$logPath = jApp::logPath('lizmap-admin.log');
$errorLog = '';
$lines = 50;
if (is_file($logPath)) {
// Only display content if the file is small to avoid memory issues
if (filesize($logPath) > 512000) {
$errorLog = 'toobig';
} else {
$errorLog = trim(implode('', array_slice(file($logPath), -$lines)));
$errorLog = htmlentities($errorLog);
}
}
$errorLog = \Lizmap\App\FileTools::tail(jApp::logPath('lizmap-admin.log'), 50);

// Display content via templates
$tpl = new jTpl();
Expand Down
79 changes: 79 additions & 0 deletions lizmap/modules/lizmap/lib/App/FileTools.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/**
* File tools for Lizmap.
*
* @author 3liz
* @copyright 2024 3liz
*
* @see https://3liz.com
*
* @license Mozilla Public License : http://www.mozilla.org/MPL/
*/

namespace Lizmap\App;

class FileTools
{
/**
* Tail in PHP, capable of eating big files.
*
* @author Torleif Berger
*
* @see http://www.geekality.net/?p=1654
*
* @return string
*/
public static function tail(string $filepath, int $lines = 10, int $buffer = 4096)
{
// Check if the file path exists and is a file
if (!file_exists($filepath) || !is_file($filepath)) {
return '';
}

// Open the file
$f = fopen($filepath, 'rb');
// Jump to last character
fseek($f, -1, SEEK_END);

// Prepare to collect output
$output = '';
$chunk = '';

// Start reading it and adjust line number if necessary
// (Otherwise the result would be wrong if file doesn't end with a blank line)
$TAIL_NL = "\n";
if (fread($f, 1) != $TAIL_NL) {
--$lines;
}

// While we would like more
while (ftell($f) > 0 && $lines >= 0) {
// Figure out how far back we should jump
$seek = min(ftell($f), $buffer);

// Do the jump (backwards, relative to where we are)
fseek($f, -$seek, SEEK_CUR);

// Read a chunk and prepend it to our output
$output = ($chunk = fread($f, $seek)).$output;

// Jump back to where we started reading
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);

// Decrease our line counter
$lines -= substr_count($chunk, $TAIL_NL);
}

// While we have too many lines
// (Because of buffer size we might have read too many)
while ($lines++ < 0) {
// Find first newline and remove all text before that
$output = substr($output, strpos($output, $TAIL_NL) + 1);
}

// Close file and return
fclose($f);

return $output;
}
}
58 changes: 1 addition & 57 deletions lizmap/modules/lizmap/lib/Request/Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ public static function getEchoFromRequest(string $url, string $body): string
$logPath = \jApp::logPath('echoproxy.log');
if (is_file($logPath)) {
// retrieve the 50 last lines
$nLastLines = preg_split("/\r\n|\n|\r/", self::tail($logPath, 50));
$nLastLines = preg_split("/\r\n|\n|\r/", App\FileTools::tail($logPath, 50));
// key : md5 , value : usefull content
$md5Assoc = array();
foreach ($nLastLines as $line) {
Expand All @@ -1032,62 +1032,6 @@ public static function getEchoFromRequest(string $url, string $body): string

return 'unfound echoproxy.log';
}

/**
* Tail in PHP, capable of eating big files.
*
* @author Torleif Berger
*
* @see http://www.geekality.net/?p=1654
*/
protected static function tail(string $filepath, int $lines = 10, int $buffer = 4096)
{
// Open the file
$f = fopen($filepath, 'rb');
// Jump to last character
fseek($f, -1, SEEK_END);

// Prepare to collect output
$output = '';
$chunk = '';

// Start reading it and adjust line number if necessary
// (Otherwise the result would be wrong if file doesn't end with a blank line)
$TAIL_NL = "\n";
if (fread($f, 1) != $TAIL_NL) {
--$lines;
}

// While we would like more
while (ftell($f) > 0 && $lines >= 0) {
// Figure out how far back we should jump
$seek = min(ftell($f), $buffer);

// Do the jump (backwards, relative to where we are)
fseek($f, -$seek, SEEK_CUR);

// Read a chunk and prepend it to our output
$output = ($chunk = fread($f, $seek)).$output;

// Jump back to where we started reading
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);

// Decrease our line counter
$lines -= substr_count($chunk, $TAIL_NL);
}

// While we have too many lines
// (Because of buffer size we might have read too many)
while ($lines++ < 0) {
// Find first newline and remove all text before that
$output = substr($output, strpos($output, $TAIL_NL) + 1);
}

// Close file and return
fclose($f);

return $output;
}
}

/*
Expand Down
31 changes: 31 additions & 0 deletions tests/units/classes/App/FileToolsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use PHPUnit\Framework\TestCase;
use Lizmap\App\FileTools;

class FileToolsTest extends TestCase
{
function testTail() {
$TAIL_NL = "\n";

$oneLinePath = __DIR__.'/Ressources/one-line.txt';
$this->assertEquals('1 line', trim(FileTools::tail($oneLinePath, 1)));
$this->assertEquals('1 line', trim(FileTools::tail($oneLinePath, 5)));

$tenLinePath = __DIR__.'/Ressources/ten-lines.txt';
$this->assertEquals('10 lines', trim(FileTools::tail($tenLinePath, 1)));

$lines = explode($TAIL_NL, trim(FileTools::tail($tenLinePath, 5)));
$this->assertCount(5, $lines);
$this->assertEquals('10 lines', $lines[4]);
$this->assertEquals('6 lines', $lines[0]);

$dirPath = __DIR__.'/Ressources';
$this->assertEquals('', trim(FileTools::tail($dirPath, 1)));
$this->assertEquals('', trim(FileTools::tail($dirPath, 5)));

$unknownPath = __DIR__.'/Ressources/unknown.txt';
$this->assertEquals('', trim(FileTools::tail($unknownPath, 1)));
$this->assertEquals('', trim(FileTools::tail($unknownPath, 5)));
}
}
1 change: 1 addition & 0 deletions tests/units/classes/App/Ressources/one-line.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1 line
10 changes: 10 additions & 0 deletions tests/units/classes/App/Ressources/ten-lines.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
1 line
2 lines
3 lines
4 lines
5 lines
6 lines
7 lines
8 lines
9 lines
10 lines

0 comments on commit 1fbb070

Please sign in to comment.