summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Brill <opensource@christophbrill.de>2026-08-03 00:39:30 +0200
committerChristoph Brill <opensource@christophbrill.de>2026-08-03 00:39:30 +0200
commit54453658f6fe48cd2288dc06345e76331ca361e3 (patch)
treebde9cefcee1a168e47bdc029f455743b29efdb72
parentda855f9dc4e8c9e230af2c578fd458e734341b9f (diff)
Read the logs line by line instead of loading them into an array
-rw-r--r--common.inc.php27
-rw-r--r--details.php8
-rwxr-xr-xjson.php10
-rw-r--r--stats.php8
4 files changed, 31 insertions, 22 deletions
diff --git a/common.inc.php b/common.inc.php
index a54fa0f..9b1b465 100644
--- a/common.inc.php
+++ b/common.inc.php
@@ -86,6 +86,33 @@ function validDate($date)
}
/**
+ * Read a log file line by line
+ *
+ * Reading the whole log using file() keeps every single line in memory at once,
+ * which for a busy day is several megabytes. All callers only walk the lines
+ * once and in order, so hand them out one at a time instead. A missing file
+ * yields nothing, the callers render their usual empty result in that case.
+ *
+ * @param string $filename the log file to read
+ *
+ * @return Generator the lines of the log, including their line endings
+ */
+function readLog($filename)
+{
+ $handle = @fopen($filename, 'r');
+ if ($handle === false) {
+ return;
+ }
+ try {
+ while (($line = fgets($handle)) !== false) {
+ yield $line;
+ }
+ } finally {
+ fclose($handle);
+ }
+}
+
+/**
* Get the date from a filename
*
* @param string $filename the filename to extract the month from (e.g.
diff --git a/details.php b/details.php
index c7fc387..1d93516 100644
--- a/details.php
+++ b/details.php
@@ -34,14 +34,8 @@ $filename = 'dri-devel-'.$date.'.log';
$pattern = '#(^|[^\"=]{1})(http://|ftp://|https://|mailto:|news:)([^\s<>]+)([\s\n<>]|$)#sm';
$timehashes = array();
-// Guard the read, a missing log would otherwise leak the full path on disk
-if (file_exists(LOG_DIR.$filename)) {
- $lines = file(LOG_DIR.$filename);
-} else {
- $lines = array();
-}
$anything_displayed = false;
-foreach ($lines as $line_num => $line) {
+foreach (readLog(LOG_DIR.$filename) as $line) {
if (isFromChannel($line, $channel)) {
if (!filterJoin($line)) {
$user = getUser($line);
diff --git a/json.php b/json.php
index 0329e4e..462a8cc 100755
--- a/json.php
+++ b/json.php
@@ -39,13 +39,7 @@ if (!isset($_GET['mode'])) {
require_once 'common.inc.php';
-// Read all lines of the log into an array
$filename = 'dri-devel-'.$date.'.log';
-if (file_exists(LOG_DIR.$filename)) {
- $lines = file(LOG_DIR.$filename);
-} else {
- $lines = array();
-}
header("Content-type: application/json;");
@@ -80,7 +74,7 @@ case 'watch':
}
// Assign all lines to a user
- foreach ($lines as $line_num => $line) {
+ foreach (readLog(LOG_DIR.$filename) as $line) {
if (isFromChannel($line, $channel)) {
if (!filterJoin($line)) {
$user = substr(getUser($line), 2, -1);
@@ -124,7 +118,7 @@ case 'watch':
case 'show':
$retval['users'] = array();
$retval['data'] = array();
- foreach ($lines as $line_num => $line) {
+ foreach (readLog(LOG_DIR.$filename) as $line) {
if (isFromChannel($line, $channel)) {
if (!filterJoin($line)) {
$user = substr(getUser($line), 2, -1);
diff --git a/stats.php b/stats.php
index 76bc776..18bc6b6 100644
--- a/stats.php
+++ b/stats.php
@@ -35,18 +35,12 @@ if (!isset($_GET['date'])) {
require_once 'common.inc.php';
-// Read all lines of the log into an array
$filename = 'dri-devel-'.$date.'.log';
-if (file_exists(LOG_DIR.$filename)) {
- $lines = file(LOG_DIR.$filename);
-} else {
- $lines = array();
-}
$retval = array();
echo '<pre>';
-foreach ($lines as $line) {
+foreach (readLog(LOG_DIR.$filename) as $line) {
$user = substr(getUser($line), 2, -1);
if ($user) {
if (in_array($user, $ignore)) {