Bearsampp 2026.7.11
Loading...
Searching...
No Matches
Log Class Reference

Static Public Member Functions

static debug ($data, $file=null)
static error ($data, $file=null)
static flush ()
static flushAsyncQueue ()
static getAsyncQueueDir ()
static getAsyncQueueSize ()
static getBufferSize ()
static getStats ()
static info ($data, $file=null)
static init ()
static initClass ($classInstance)
static isAsyncEnabled ()
static processAsyncQueue ()
static reloadClass ($classInstance)
static reset ()
static separator ()
static setAsyncEnabled ($enabled)
static setBufferSize ($size)
static trace ($data, $file=null)
static warning ($data, $file=null)

Data Fields

const DEBUG = 'DEBUG'
const ERROR = 'ERROR'
const INFO = 'INFO'
const TRACE = 'TRACE'
const WARNING = 'WARNING'

Static Private Member Functions

static checkVerbosityAndAdjustAsync ()
static cleanupStaleAsyncQueue ($maxAge)
static initializeAsyncQueue ()
static queueAsyncWrite ($file, $content)
static write ($data, $type, $file=null)

Static Private Attributes

static $asyncEnabled = true
static $asyncQueueDir = null
static $logBuffer = []
static $logBufferSize = 50
static $logStats
static $maxAsyncQueueBatch = 5
static $shutdownRegistered = false

Detailed Description

Log class providing static logging methods with buffered and asynchronous I/O.

Supports five log levels (TRACE, DEBUG, INFO, WARNING, ERROR), a separator utility, class-lifecycle helpers, and a configurable write buffer to reduce file-system pressure. Also supports asynchronous logging to decouple I/O operations from the main process.

Call Log\init() once during bootstrap (after globals are available) to register the shutdown flush handler and initialize async logging.

Usage:

Log::info('Application started');
Log::error('Something went wrong');
static info($data, $file=null)
static init()
Definition class.log.php:72
static error($data, $file=null)

Definition at line 29 of file class.log.php.

Member Function Documentation

◆ checkVerbosityAndAdjustAsync()

checkVerbosityAndAdjustAsync ( )
staticprivate

Check logging verbosity and adjust async settings accordingly. Disables async when TRACE level is enabled for real-time log visibility. Also optimizes buffer size for better responsiveness during debugging.

Returns
void

Definition at line 94 of file class.log.php.

95 {
96 global $bearsamppConfig;
97
98 try {
99 if (!isset($bearsamppConfig)) {
100 return;
101 }
102
103 $verbosity = $bearsamppConfig->getLogsVerbose();
104
105 // Disable async and reduce buffer size for DEBUG/TRACE logging
106 // This ensures live log monitoring shows logs immediately
107 if ($verbosity === Config::VERBOSE_TRACE) {
108 self::$asyncEnabled = false;
109 // Use smaller buffer for TRACE to flush more frequently (every 10 entries)
110 self::$logBufferSize = 10;
111 } elseif ($verbosity === Config::VERBOSE_DEBUG) {
112 self::$asyncEnabled = false;
113 // For DEBUG level, use moderate buffer size (25 entries)
114 self::$logBufferSize = 25;
115 }
116 // For INFO and REPORT levels, use default buffer size (50) with async enabled
117 } catch (Exception $e) {
118 // Silently fail - this is just an optimization
119 }
120 }
const VERBOSE_TRACE
const VERBOSE_DEBUG
global $bearsamppConfig
Definition homepage.php:41

References $bearsamppConfig, Config\VERBOSE_DEBUG, and Config\VERBOSE_TRACE.

Referenced by init().

Here is the caller graph for this function:

◆ cleanupStaleAsyncQueue()

cleanupStaleAsyncQueue ( $maxAge)
staticprivate

Clean up stale queue files that weren't processed. Prevents queue directory from filling up with old entries.

Parameters
int$maxAgeMaximum age in seconds
Returns
int Number of files removed

Definition at line 437 of file class.log.php.

438 {
439 if (!is_dir(self::$asyncQueueDir)) {
440 return 0;
441 }
442
443 $removed = 0;
444 $now = time();
445
446 try {
447 $queueFiles = @glob(self::$asyncQueueDir . '/*.queue');
448
449 if (!is_array($queueFiles)) {
450 return 0;
451 }
452
453 foreach ($queueFiles as $queueFile) {
454 try {
455 // Remove files older than maxAge
456 if ($now - @filemtime($queueFile) > $maxAge) {
457 @unlink($queueFile);
458 $removed++;
459 }
460 } catch (Exception $e) {
461 // Skip
462 }
463 }
464 } catch (Exception $e) {
465 // Ignore cleanup errors
466 }
467
468 return $removed;
469 }

Referenced by processAsyncQueue().

Here is the caller graph for this function:

◆ debug()

debug ( $data,
$file = null )
static

Logs a DEBUG-level message.

Parameters
mixed$data
string | null$file

Definition at line 616 of file class.log.php.

617 {
618 self::write($data, self::DEBUG, $file);
619 }
static write($data, $type, $file=null)

References write().

Referenced by ActionCheckVersion\__construct(), ActionQuit\__construct(), Action\call(), Path\changePath(), BinApache\changePort(), BinMailpit\changePort(), BinMariadb\changePort(), BinMemcached\changePort(), BinMysql\changePort(), BinPostgresql\changePort(), BinXlight\changePort(), QuickPick\checkDownloadId(), ActionQuit\checkForOrphanedProcesses(), BinApache\checkPort(), BinMailpit\checkPort(), BinMariadb\checkPort(), BinMemcached\checkPort(), BinMysql\checkPort(), BinPostgresql\checkPort(), BinXlight\checkPort(), Csrf\cleanupExpiredTokens(), ActionQuit\cleanupTemporaryFiles(), Win32Native\countFilesFolders(), Win32Native\countFilesFoldersCOM(), Win32Native\createShortcut(), QuickPick\fetchAndUnzipModule(), Csrf\generateToken(), Registry\getAppBinsRegKey(), Win32Native\getDefaultBrowser(), Util\getFilesToScan(), HttpClient\getHeaders(), Util\getHeaders(), HttpClient\getHttpHeaders(), Util\getHttpHeaders(), Win32Native\getInstalledBrowsers(), HttpClient\getLatestVersion(), Util\getLatestVersion(), QuickPick\getModuleUrl(), Win32Native\getProcessList(), Win32Native\getServiceInfo(), Win32Native\getSpecialFolderPath(), QuickPick\getVersions(), BinPostgresql\handleNonPostgresUsage(), Win32Service\infos(), QuickPick\installModule(), Win32Native\killProcess(), Win32Native\listServices(), ModuleLoader\loadAsync(), ModuleLoader\loadSync(), QuickPick\logHeaders(), ActionQuit\performQuickCleanupVerification(), Action\process(), ActionQuit\processWindow(), QuickPick\rebuildQuickpickJson(), BinApache\refreshAlias(), BinApache\refreshConf(), BinApache\refreshVhosts(), QuickPick\regenerateMenuSafe(), Win32Native\registryDeleteKey(), Win32Native\registryDeleteValue(), Win32Native\registryExists(), Win32Native\registryGetValue(), Win32Native\registrySetValue(), Symlinks\safeRemoveSymlink(), ActionStartup\scanFolders(), Cache\set(), Cache\setDuration(), BinApache\setEnable(), BinMailpit\setEnable(), BinMariadb\setEnable(), BinMemcached\setEnable(), BinMysql\setEnable(), BinNodejs\setEnable(), BinPhp\setEnable(), BinPostgresql\setEnable(), BinXlight\setEnable(), ActionCheckVersion\showVersionOkMessageBox(), Win32Service\start(), BinApache\switchVersion(), BinMailpit\switchVersion(), BinMariadb\switchVersion(), BinMemcached\switchVersion(), BinMysql\switchVersion(), BinNodejs\switchVersion(), BinPhp\switchVersion(), BinPostgresql\switchVersion(), BinXlight\switchVersion(), Core\unzipFile(), AppPhpmyadmin\updateConfig(), AppPhppgadmin\updateConfig(), BinApache\updateConfig(), BinMailpit\updateConfig(), BinMariadb\updateConfig(), BinMemcached\updateConfig(), BinMysql\updateConfig(), BinNodejs\updateConfig(), BinPhp\updateConfig(), BinPostgresql\updateConfig(), BinXlight\updateConfig(), Module\updateConfig(), ToolGit\updateConfig(), QuickPick\updateModuleConfig(), Csrf\validateToken(), ActionQuit\verifyServicesStoppedAndCleanup(), ActionStartup\writeLog(), Batch\writeLog(), CommandRunner\writeLog(), Nssm\writeLog(), Registry\writeLog(), Win32Service\writeLog(), and WinBinder\writeLog().

Here is the call graph for this function:

◆ error()

error ( $data,
$file = null )
static

Logs an ERROR-level message. Errors bypass the buffer and are written immediately.

Parameters
mixed$data
string | null$file

Definition at line 650 of file class.log.php.

651 {
652 self::write($data, self::ERROR, $file);
653 }

References write().

Referenced by ActionCheckVersion\__construct(), ActionLoading\__construct(), FiberModule\__construct(), Path\changePath(), BinApache\changePort(), BinMailpit\changePort(), BinMariadb\changePort(), BinMemcached\changePort(), BinMysql\changePort(), BinPostgresql\changePort(), BinXlight\changePort(), QuickPick\checkDownloadId(), ActionQuit\checkForOrphanedProcesses(), BinApache\checkPort(), BinMailpit\checkPort(), BinMariadb\checkPort(), BinMemcached\checkPort(), BinMysql\checkPort(), BinPostgresql\checkPort(), BinXlight\checkPort(), ActionQuit\cleanupTemporaryFiles(), Win32Native\countFilesFolders(), Win32Native\countFilesFoldersCOM(), OpenSsl\createCrt(), Symlinks\createModuleSymlink(), Win32Native\createShortcut(), ActionStartup\createSslCrts(), Symlinks\deleteCurrentSymlinks(), Util\deleteFolder(), OpenSsl\ensureMkcertExeExists(), OpenSsl\ensureRootCaExists(), OpenSsl\ensureSslDirExists(), QuickPick\fetchAndUnzipModule(), Win32Native\findProcessesByName(), UtilString\generateSecureBytes(), UtilString\generateSecureToken(), Csrf\generateToken(), HttpClient\getApiJson(), Util\getApiJson(), Core\getAppVersion(), Cache\getCacheIntegrityKey(), Core\getFileFromUrl(), HttpClient\getLatestVersion(), Util\getLatestVersion(), QuickPick\getModuleUrl(), Win32Native\getProcessInfo(), Win32Native\getProcessList(), QuickPick\getQuickpickJson(), Win32Native\getServiceInfo(), Win32Native\getSpecialFolderPath(), QuickPick\getVersions(), Splash\init(), BinMariadb\initData(), QuickPick\installModule(), Util\installService(), OpenSsl\isExpired(), Symlinks\isPathWithinAllowedBase(), Win32Native\killProcess(), Win32Native\listServices(), OpenSsl\makeRootCa(), ActionCheckVersion\processWindow(), UtilString\random(), OpenSsl\rebuildAllCerts(), Win32Native\registryDeleteKey(), Win32Native\registryDeleteValue(), Win32Native\registryExists(), Win32Native\registrySetValue(), AppPhpmyadmin\reload(), AppPhppgadmin\reload(), BinApache\reload(), BinMailpit\reload(), BinMariadb\reload(), BinMemcached\reload(), BinMysql\reload(), BinNodejs\reload(), BinPhp\reload(), BinPostgresql\reload(), BinXlight\reload(), ToolBruno\reload(), ToolComposer\reload(), ToolGhostscript\reload(), ToolGit\reload(), ToolNgrok\reload(), ToolPerl\reload(), ToolPowerShell\reload(), ToolPython\reload(), ToolRuby\reload(), OpenSsl\removeCrt(), Util\removeService(), Symlinks\safeRemoveSymlink(), Win32Service\start(), Util\startService(), Win32Service\stop(), TplAppReload\triggerReload(), Core\unzipFile(), AppPhpmyadmin\updateConfig(), AppPhppgadmin\updateConfig(), BinApache\updateConfig(), BinMailpit\updateConfig(), BinMariadb\updateConfig(), BinMemcached\updateConfig(), BinMysql\updateConfig(), BinNodejs\updateConfig(), BinPhp\updateConfig(), BinPostgresql\updateConfig(), BinXlight\updateConfig(), QuickPick\updateModuleConfig(), ActionQuit\verifyServicesStoppedAndCleanup(), ActionQuit\verifySymlinksRemoved(), FiberModule\wait(), ModuleLoader\waitForModule(), and Nssm\writeLogError().

Here is the call graph for this function:

◆ flush()

flush ( )
static

Flushes the log buffer to disk using async writes when available. Groups entries by file to minimise file operations. Uses async logging to avoid blocking the main process on I/O. Falls back to synchronous writes or error_log() if needed.

Returns
void

Definition at line 228 of file class.log.php.

229 {
230 if (empty(self::$logBuffer)) {
231 return;
232 }
233
235
236 // If the core global is gone (e.g. during an abnormal shutdown), fall back to error_log
237 if (!isset($bearsamppCore)) {
238 foreach (self::$logBuffer as $log) {
239 error_log('[' . date('Y-m-d H:i:s', $log['time']) . '] [' . $log['type'] . '] ' . $log['data']);
240 }
241 self::$logStats['flushed'] += count(self::$logBuffer);
242 self::$logBuffer = [];
243 return;
244 }
245
246 // Check if DEBUG or TRACE logging is active and force sync writes
247 $forceSync = false;
248 try {
249 if (isset($bearsamppConfig)) {
250 $verbosity = $bearsamppConfig->getLogsVerbose();
251 if ($verbosity === Config::VERBOSE_TRACE || $verbosity === Config::VERBOSE_DEBUG) {
252 $forceSync = true;
253 }
254 }
255 } catch (Exception $e) {
256 // Ignore errors checking config
257 }
258
259 // Group logs by destination file
260 $logsByFile = [];
261 foreach (self::$logBuffer as $log) {
262 $logsByFile[$log['file']][] = $log;
263 }
264
265 foreach ($logsByFile as $file => $logs) {
266 $content = '';
267 foreach ($logs as $log) {
268 $content .= '[' . date('Y-m-d H:i:s', $log['time']) . '] # ' .
269 APP_TITLE . ' ' . $bearsamppCore->getAppVersion() . ' # ' .
270 $log['type'] . ': ' . $log['data'] . PHP_EOL;
271 }
272
273 // Use sync writes if TRACE is enabled or async is disabled
274 if (!$forceSync && self::$asyncEnabled) {
275 // Queue for async processing (non-blocking)
276 $queued = self::queueAsyncWrite($file, $content);
277
278 if ($queued) {
279 // Successfully queued, content will be written in background
280 self::$logStats['async']++;
281 self::$logStats['writes']++;
282 continue;
283 }
284 // If async queueing failed, fall through to sync write
285 }
286
287 // Synchronous write (immediate for TRACE, fallback for others)
288 $written = @file_put_contents($file, $content, FILE_APPEND | LOCK_EX);
289 if ($written === false) {
290 // File write failed — ensure entries are not silently lost
291 foreach ($logs as $log) {
292 error_log('[' . $log['type'] . '] ' . $log['data'] . ' (target: ' . $file . ')');
293 }
294 }
295
296 self::$logStats['writes']++;
297 }
298
299 self::$logStats['flushed'] += count(self::$logBuffer);
300 self::$logBuffer = [];
301 }
global $bearsamppCore
static queueAsyncWrite($file, $content)
const APP_TITLE
Definition root.php:13

References $bearsamppConfig, $bearsamppCore, APP_TITLE, queueAsyncWrite(), Config\VERBOSE_DEBUG, and Config\VERBOSE_TRACE.

Referenced by write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ flushAsyncQueue()

flushAsyncQueue ( )
static

Process all queued log entries immediately (public method for manual flushing). Useful for live log monitoring or ensuring logs are written before critical operations.

Can be called at any time to flush pending async log writes.

Returns
int Number of queue files processed

Definition at line 347 of file class.log.php.

348 {
350 }
static processAsyncQueue()

References processAsyncQueue().

Here is the call graph for this function:

◆ getAsyncQueueDir()

getAsyncQueueDir ( )
static

Get the async queue directory path.

Returns
string|null

Definition at line 515 of file class.log.php.

516 {
517 return self::$asyncQueueDir;
518 }

◆ getAsyncQueueSize()

getAsyncQueueSize ( )
static

Get current async queue size.

Returns
int

Definition at line 525 of file class.log.php.

526 {
527 if (!is_dir(self::$asyncQueueDir)) {
528 return 0;
529 }
530
531 $files = @glob(self::$asyncQueueDir . '/*.queue');
532 return is_array($files) ? count($files) : 0;
533 }

◆ getBufferSize()

getBufferSize ( )
static

Returns the current log buffer size.

Returns
int

Definition at line 563 of file class.log.php.

564 {
565 return self::$logBufferSize;
566 }

◆ getStats()

getStats ( )
static

Returns the current log buffer statistics.

Returns
array Array with keys 'buffered', 'flushed', and 'writes'.

Definition at line 540 of file class.log.php.

541 {
542 return self::$logStats;
543 }

◆ info()

info ( $data,
$file = null )
static

Logs an INFO-level message.

Parameters
mixed$data
string | null$file

Definition at line 627 of file class.log.php.

628 {
629 self::write($data, self::INFO, $file);
630 }

References write().

Referenced by ActionQuit\__construct(), ActionStartup\__construct(), ActionQuit\checkForOrphanedProcesses(), ActionQuit\cleanupTemporaryFiles(), Cache\clear(), ActionStartup\createSslCrts(), OpenSsl\ensureRootCaExists(), OpenSsl\ensureSslDirExists(), Batch\exitApp(), Util\getFilesToScan(), Util\installService(), ActionStartup\installServicesSequential(), OpenSsl\makeRootCa(), ActionQuit\performQuickCleanupVerification(), ActionQuit\processWindow(), OpenSsl\rebuildAllCerts(), AppPhpmyadmin\reload(), AppPhppgadmin\reload(), Apps\reload(), BinApache\reload(), BinMailpit\reload(), BinMariadb\reload(), BinMemcached\reload(), BinMysql\reload(), BinNodejs\reload(), BinPhp\reload(), BinPostgresql\reload(), Bins\reload(), BinXlight\reload(), ToolBruno\reload(), ToolComposer\reload(), ToolGhostscript\reload(), ToolGit\reload(), ToolNgrok\reload(), ToolPerl\reload(), ToolPowerShell\reload(), ToolPython\reload(), ToolRuby\reload(), OpenSsl\removeCrt(), Util\removeService(), BinApache\setEnable(), BinMailpit\setEnable(), BinMariadb\setEnable(), BinMemcached\setEnable(), BinMysql\setEnable(), BinNodejs\setEnable(), BinPhp\setEnable(), BinPostgresql\setEnable(), BinXlight\setEnable(), Win32Service\start(), ServiceHelper\startAllServicesParallel(), ServiceHelper\stopAllServicesParallel(), Apps\update(), Bins\update(), Tools\update(), QuickPick\updateModuleConfig(), ActionQuit\verifyServicesStoppedAndCleanup(), ActionQuit\verifySymlinksRemoved(), and Nssm\writeLogInfo().

Here is the call graph for this function:

◆ init()

init ( )
static

Registers the shutdown flush handler and initializes async logging. Call once during bootstrap after globals are initialised.

Automatically disables async logging when TRACE verbosity is enabled, to ensure live log monitoring shows logs immediately.

Returns
void

Definition at line 72 of file class.log.php.

73 {
74 if (!self::$shutdownRegistered) {
75 register_shutdown_function([__CLASS__, 'flush']);
76 register_shutdown_function([__CLASS__, 'processAsyncQueue']);
77 self::$shutdownRegistered = true;
78
79 // Initialize async queue directory
81
82 // Auto-disable async when TRACE logging is enabled (for live log monitoring)
84 }
85 }
static initializeAsyncQueue()
static checkVerbosityAndAdjustAsync()
Definition class.log.php:94

References checkVerbosityAndAdjustAsync(), and initializeAsyncQueue().

Referenced by Root\register(), and write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initClass()

◆ initializeAsyncQueue()

initializeAsyncQueue ( )
staticprivate

Initialize async queue directory.

Returns
void

Definition at line 127 of file class.log.php.

128 {
129 try {
130 // Set up queue directory in tmp
131 self::$asyncQueueDir = Path::getTmpPath() . '/log-queue';
132
133 // Create queue directory if it doesn't exist
134 if (!is_dir(self::$asyncQueueDir)) {
135 @mkdir(self::$asyncQueueDir, 0755, true);
136 }
137 } catch (Exception $e) {
138 self::$asyncEnabled = false;
139 }
140 }
static getTmpPath($aetrayPath=false)

References Path\getTmpPath().

Referenced by init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isAsyncEnabled()

isAsyncEnabled ( )
static

Check if async logging is enabled.

Returns
bool

Definition at line 505 of file class.log.php.

506 {
507 return self::$asyncEnabled;
508 }

◆ processAsyncQueue()

processAsyncQueue ( )
static

Process all queued log entries at shutdown. Ensures any remaining queued logs are written before exit.

Returns
int Number of queue files processed

Definition at line 358 of file class.log.php.

359 {
360 if (!is_dir(self::$asyncQueueDir)) {
361 return 0;
362 }
363
364 $processed = 0;
365
366 try {
367 $queueFiles = glob(self::$asyncQueueDir . '/*.queue');
368
369 if (empty($queueFiles)) {
370 return 0;
371 }
372
373 // Group entries by target file
374 $entriesByFile = [];
375
376 foreach ($queueFiles as $queueFile) {
377 try {
378 // Read and deserialize queue entry
379 $serialized = @file_get_contents($queueFile);
380 if ($serialized === false) {
381 continue;
382 }
383
384 $entry = @unserialize($serialized, ['allowed_classes' => false]);
385 if ($entry === false || !isset($entry['file']) || !isset($entry['content'])) {
386 // Invalid queue entry, remove it
387 @unlink($queueFile);
388 continue;
389 }
390
391 // Group by target file
392 $targetFile = $entry['file'];
393 if (!isset($entriesByFile[$targetFile])) {
394 $entriesByFile[$targetFile] = [];
395 }
396
397 $entriesByFile[$targetFile][] = $entry['content'];
398 $processed++;
399
400 // Remove the processed queue file
401 @unlink($queueFile);
402
403 } catch (Exception $e) {
404 // Skip bad entries
405 @unlink($queueFile);
406 }
407 }
408
409 // Write all accumulated entries to their target files
410 foreach ($entriesByFile as $targetFile => $contents) {
411 try {
412 $combined = implode('', $contents);
413 @file_put_contents($targetFile, $combined, FILE_APPEND | LOCK_EX);
414 } catch (Exception $e) {
415 // Log write failed - use error_log as fallback
416 error_log('Failed to write to ' . $targetFile);
417 }
418 }
419
420 // Clean up any stale queue files
422
423 } catch (Exception $e) {
424 // Silently fail
425 }
426
427 return $processed;
428 }
static cleanupStaleAsyncQueue($maxAge)

References cleanupStaleAsyncQueue().

Referenced by flushAsyncQueue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queueAsyncWrite()

queueAsyncWrite ( $file,
$content )
staticprivate

Queue a log entry for asynchronous writing. Returns immediately without blocking on I/O.

Parameters
string$fileTarget log file path
string$contentLog content to write
Returns
bool True if queued successfully

Definition at line 311 of file class.log.php.

312 {
313 if (!self::$asyncEnabled || !is_dir(self::$asyncQueueDir)) {
314 return false;
315 }
316
317 try {
318 // Create a unique queue file for this write
319 $queueFile = self::$asyncQueueDir . '/' . uniqid('log_', true) . '.queue';
320
321 // Queue entry contains the target file and content
322 $queueEntry = [
323 'file' => $file,
324 'content' => $content,
325 'timestamp' => time(),
326 ];
327
328 // Write queue entry (this is a small, fast operation)
329 $serialized = serialize($queueEntry);
330 $written = @file_put_contents($queueFile, $serialized, LOCK_EX);
331
332 return ($written !== false);
333 } catch (Exception $e) {
334 // Silently fail - this is async so we don't want to interrupt main process
335 return false;
336 }
337 }

Referenced by flush().

Here is the caller graph for this function:

◆ reloadClass()

reloadClass ( $classInstance)
static

Logs the reloading of a class instance at TRACE level.

Parameters
object$classInstance

Definition at line 670 of file class.log.php.

671 {
672 self::trace('Reload ' . get_class($classInstance));
673 }

References trace().

Referenced by AppPhpmyadmin\reload(), AppPhppgadmin\reload(), BinApache\reload(), BinMailpit\reload(), BinMariadb\reload(), BinMemcached\reload(), BinMysql\reload(), BinNodejs\reload(), BinPhp\reload(), BinPostgresql\reload(), BinXlight\reload(), ToolBruno\reload(), ToolComposer\reload(), ToolGhostscript\reload(), ToolGit\reload(), ToolNgrok\reload(), ToolPerl\reload(), ToolPowerShell\reload(), ToolPython\reload(), and ToolRuby\reload().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset()

reset ( )
static

Clears the buffer and resets statistics. Useful in tests or when re-initialising the application.

Returns
void

Definition at line 477 of file class.log.php.

478 {
479 self::$logBuffer = [];
480 self::$shutdownRegistered = false;
481 self::$logStats = [
482 'buffered' => 0,
483 'flushed' => 0,
484 'writes' => 0,
485 'async' => 0,
486 ];
487 }

◆ separator()

separator ( )
static

Appends a separator line to each log file that does not already end with one.

@global object $bearsamppRoot

Definition at line 573 of file class.log.php.

574 {
575 global $bearsamppRoot;
576
577 $logs = [
585 ];
586
587 $separator = '========================================================================================' . PHP_EOL;
588 foreach ($logs as $log) {
589 if (!file_exists($log)) {
590 continue;
591 }
592 $logContent = @file_get_contents($log);
593 if ($logContent !== false && !str_ends_with($logContent, $separator)) {
594 file_put_contents($log, $separator, FILE_APPEND);
595 }
596 }
597 }
global $bearsamppRoot
static getBatchLogFilePath($aetrayPath=false)
static getLogFilePath($aetrayPath=false)
static getStartupLogFilePath($aetrayPath=false)
static getServicesLogFilePath($aetrayPath=false)
static getRegistryLogFilePath($aetrayPath=false)
static getErrorLogFilePath($aetrayPath=false)
static getWinbinderLogFilePath($aetrayPath=false)

References $bearsamppRoot, Path\getBatchLogFilePath(), Path\getErrorLogFilePath(), Path\getLogFilePath(), Path\getRegistryLogFilePath(), Path\getServicesLogFilePath(), Path\getStartupLogFilePath(), and Path\getWinbinderLogFilePath().

Referenced by Root\register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setAsyncEnabled()

setAsyncEnabled ( $enabled)
static

Enable or disable async logging.

Parameters
bool$enabled
Returns
void

Definition at line 495 of file class.log.php.

496 {
497 self::$asyncEnabled = (bool)$enabled;
498 }

◆ setBufferSize()

setBufferSize ( $size)
static

Sets the log buffer size.

Parameters
int$sizeNew buffer size (1–1000).
Returns
void

Definition at line 551 of file class.log.php.

552 {
553 if ($size > 0 && $size <= 1000) {
554 self::$logBufferSize = $size;
555 }
556 }

◆ trace()

trace ( $data,
$file = null )
static

Logs a TRACE-level message.

Parameters
mixed$data
string | null$file

Definition at line 605 of file class.log.php.

606 {
607 self::write($data, self::TRACE, $file);
608 }

References write().

Referenced by ActionExec\__construct(), ActionLoading\__construct(), ActionManualRestart\__construct(), ActionRebuildini\__construct(), Win32Service\callWin32Service(), BinMysql\changeRootPassword(), ActionLoading\checkAllServicesStarted(), ActionStartup\checkApacheServiceWithTimeout(), ActionStartup\checkMySQLServiceWithTimeout(), BinMysql\checkPort(), BinMysql\checkRootPassword(), Win32Service\create(), OpenSsl\createCrt(), ActionStartup\createSslCrts(), Win32Service\delete(), Symlinks\deleteCurrentSymlinks(), Win32Service\ensureReset(), Win32Service\fastServiceCheck(), ServiceHelper\forceKillService(), HttpClient\getCurlHttpHeaders(), Util\getCurlHttpHeaders(), Win32Service\getServices(), Win32Service\infos(), initClass(), BinMariadb\initData(), BinMysql\initData(), ActionStartup\installServices(), ActionStartup\installServicesSequential(), OpenSsl\isExpired(), Win32Service\isInstalled(), Win32Service\isPaused(), Win32Service\isPending(), Win32Service\isRunning(), Win32Service\isStopped(), ActionStartup\prepareService(), ActionLoading\processLoading(), ActionQuit\processWindow(), ActionStartup\processWindow(), ActionSwitchVersion\processWindow(), BinMailpit\rebuildConf(), BinApache\refreshAlias(), BinApache\refreshConf(), BinApache\refreshVhosts(), reloadClass(), Config\replaceAll(), Util\replaceInFile(), ActionStartup\rotationLogs(), Symlinks\safeRemoveSymlink(), ActionStartup\scanFolders(), BinMailpit\setVersion(), BinPhp\setVersion(), ServiceHelper\shutdownServicesParallel(), ServiceHelper\shutdownServicesSequential(), ServiceHelper\startAllServicesParallel(), Util\startLoading(), ServiceHelper\startServicesParallel(), ServiceHelper\startServicesSequential(), Win32Service\status(), Win32Service\stop(), ServiceHelper\stopAllServicesParallel(), ActionQuit\terminatePhpProcesses(), TplAppReload\triggerReload(), Core\unzipFile(), BinPhp\updateConfig(), ActionSwitchVersion\updateConfigVersion(), and Win32Service\waitForServiceDeletion().

Here is the call graph for this function:

◆ warning()

◆ write()

write ( $data,
$type,
$file = null )
staticprivate

Writes a message to a log file, using the buffer to reduce I/O.

The file path is resolved as follows:

  • If $file is provided by the caller it is used as-is.
  • Otherwise the default path is chosen based on $type (error log vs. main log), then overridden with the homepage log when not running in root context.
Parameters
mixed$dataThe message to log.
string$typeOne of the Log level constants.
string | null$fileExplicit file path, or null to use the default.

Definition at line 154 of file class.log.php.

155 {
157
158 // Safety check: if globals aren't initialised, fall back to error_log
159 if (!isset($bearsamppRoot) || !isset($bearsamppCore) || !isset($bearsamppConfig)) {
160 error_log('[' . $type . '] ' . $data);
161 return;
162 }
163
164 // Lazily register the shutdown handler if init() was not called explicitly
165 self::init();
166
167 // Resolve default file path only when the caller did not supply one
168 if ($file === null) {
169 $file = $type === self::ERROR
171 : Path::getLogFilePath();
172
173 if (!$bearsamppRoot->isRoot()) {
174 $file = Path::getHomepageLogFilePath();
175 }
176 }
177
178 $verbose = [];
179 $verbose[Config::VERBOSE_SIMPLE] = $type === self::ERROR || $type === self::WARNING;
180 $verbose[Config::VERBOSE_REPORT] = $verbose[Config::VERBOSE_SIMPLE] || $type === self::INFO;
181 $verbose[Config::VERBOSE_DEBUG] = $verbose[Config::VERBOSE_REPORT] || $type === self::DEBUG;
182 $verbose[Config::VERBOSE_TRACE] = $verbose[Config::VERBOSE_DEBUG] || $type === self::TRACE;
183
184 $writeLog = false;
185 if ($bearsamppConfig->getLogsVerbose() === Config::VERBOSE_SIMPLE && $verbose[Config::VERBOSE_SIMPLE]) {
186 $writeLog = true;
187 } elseif ($bearsamppConfig->getLogsVerbose() === Config::VERBOSE_REPORT && $verbose[Config::VERBOSE_REPORT]) {
188 $writeLog = true;
189 } elseif ($bearsamppConfig->getLogsVerbose() === Config::VERBOSE_DEBUG && $verbose[Config::VERBOSE_DEBUG]) {
190 $writeLog = true;
191 } elseif ($bearsamppConfig->getLogsVerbose() === Config::VERBOSE_TRACE && $verbose[Config::VERBOSE_TRACE]) {
192 $writeLog = true;
193 }
194
195 if ($writeLog) {
196 self::$logBuffer[] = [
197 'file' => $file,
198 'data' => $data,
199 'type' => $type,
200 'time' => time(),
201 ];
202 self::$logStats['buffered']++;
203
204 // Flush immediately for:
205 // 1. Errors (always)
206 // 2. TRACE/DEBUG level logs (for real-time visibility during debugging)
207 // 3. When buffer reaches the configured size limit
208 $debugVerbosity = $bearsamppConfig->getLogsVerbose();
209 $isDebugMode = ($debugVerbosity === Config::VERBOSE_TRACE || $debugVerbosity === Config::VERBOSE_DEBUG);
210 $shouldFlush = $type === self::ERROR ||
211 $isDebugMode ||
212 count(self::$logBuffer) >= self::$logBufferSize;
213
214 if ($shouldFlush) {
215 self::flush();
216 }
217 }
218 }
const VERBOSE_REPORT
const VERBOSE_SIMPLE
static flush()

References $bearsamppConfig, $bearsamppCore, $bearsamppRoot, flush(), Path\getErrorLogFilePath(), Path\getHomepageLogFilePath(), Path\getLogFilePath(), init(), Config\VERBOSE_DEBUG, Config\VERBOSE_REPORT, Config\VERBOSE_SIMPLE, and Config\VERBOSE_TRACE.

Referenced by debug(), error(), info(), trace(), and warning().

Here is the call graph for this function:
Here is the caller graph for this function:

Field Documentation

◆ $asyncEnabled

$asyncEnabled = true
staticprivate

Definition at line 58 of file class.log.php.

◆ $asyncQueueDir

$asyncQueueDir = null
staticprivate

Definition at line 55 of file class.log.php.

◆ $logBuffer

$logBuffer = []
staticprivate

Definition at line 38 of file class.log.php.

◆ $logBufferSize

$logBufferSize = 50
staticprivate

Definition at line 41 of file class.log.php.

◆ $logStats

$logStats
staticprivate
Initial value:
= [
'buffered' => 0,
'flushed' => 0,
'writes' => 0,
'async' => 0,
]

Definition at line 47 of file class.log.php.

◆ $maxAsyncQueueBatch

$maxAsyncQueueBatch = 5
staticprivate

Definition at line 61 of file class.log.php.

◆ $shutdownRegistered

$shutdownRegistered = false
staticprivate

Definition at line 44 of file class.log.php.

◆ DEBUG

const DEBUG = 'DEBUG'

Definition at line 34 of file class.log.php.

◆ ERROR

const ERROR = 'ERROR'

Definition at line 31 of file class.log.php.

◆ INFO

const INFO = 'INFO'

Definition at line 33 of file class.log.php.

◆ TRACE

const TRACE = 'TRACE'

Definition at line 35 of file class.log.php.

◆ WARNING

const WARNING = 'WARNING'

Definition at line 32 of file class.log.php.


The documentation for this class was generated from the following file: