Last active
February 8, 2018 09:03
-
-
Save abraovic/b2978782b13a77479ca1f59df0d11e08 to your computer and use it in GitHub Desktop.
Enables simple logging into a file for php applications. It is tested only on linux machines so it will need some improvements to work on other platforms.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$logger = new SimpleLogger([ | |
'log_file' => '/opt/symfony/app/cache/simplelogger/my.log', | |
'max_log_file_size' => 3, | |
'clean_old_files' => true, | |
'max_log_file_archive' => 3, | |
'log_backtrace' => true | |
]); | |
$logger->info('test'); | |
$logger->warning('test'); // log line expample [WARNING] - 27.09.2016, Tuesday, @ 13:35:49 - test | |
$logger->error('test'); | |
// config explanations: | |
// log_file (string) -> full path to log file (default: /tmp/simple_logger/simple_logger.log) | |
// max_log_file_size (int) -> number of lines that single log file can have (default: 1000) | |
// clean_old_files (bool) -> true/false which defines if system should clean old archive files (default: false) | |
// max_log_file_archive (int) -> defines what is max limit of archives that won't be deleted if previous property is true | |
// (default: 10) | |
// log_backtrace (bool) -> when log line is created at the end of it is added file path and line where is it called from | |
// (default: false) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* The MIT License (MIT) | |
* Copyright (c) 2016 Ante Braović - abraovic@gmail.com - antebraovic.me | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |
* and associated documentation files (the "Software"), to deal in the Software without restriction, including | |
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to | |
* the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all copies or substantial | |
* portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT | |
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO | |
* EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE | |
* OR OTHER DEALINGS IN THE SOFTWARE. | |
* | |
* @author Ante Braović - abraovic@gmail.com - antebraovic.me | |
*/ | |
class SimpleLogger | |
{ | |
const INFO = "INFO"; | |
const WARNING = "WARNING"; | |
const ERROR = "ERROR"; | |
/** | |
* Defines where logs will be stored. Default value is /tmp/simple_logger/simple_logger.log. | |
* You can change the default by setting this attribute. | |
* | |
* @var string $logFile | |
*/ | |
private $logFile = "/tmp/simple_logger/simple_logger.log"; | |
/** | |
* Defines max number of lines single file can have. If the file reaches limit, new | |
* file will be created. Default value is 1000. | |
* You can change the default by setting this attribute. | |
* | |
* @var int $maxLogFileSize | |
*/ | |
private $maxLogFileSize = 1000; | |
/** | |
* Defines should the system clean old log files. Default value is false. If it is | |
* set as true default file age is one month. | |
* You can change the default by setting this attribute. | |
* | |
* @var bool $cleanOldFiles | |
*/ | |
private $cleanOldFiles = false; | |
/** | |
* Defines how long should system keep archive log files. Default value is 10 which means that | |
* archives > simple_logger.log10 will be deleted if $cleanOldFiles is true | |
* You can change the default by setting this attribute. | |
* | |
* @var int $maxLogFileArchive | |
*/ | |
private $maxLogFileArchive = 10; | |
/** | |
* Defines if logger should write down file and line number from where that line has been | |
* called. Default value is false. | |
* You can change the default by setting this attribute. | |
* | |
* @var bool $logBacktrace | |
*/ | |
private $logBacktrace = false; | |
/** | |
* @constructor | |
* @param $config -> array that holds configuration options | |
*/ | |
function __construct($config = [ | |
'log_file' => '', | |
'max_log_file_size' => 0, | |
'clean_old_files' => false, | |
'max_log_file_archive' => 0, | |
'log_backtrace' => false | |
]) { | |
$this->logFile = $config['log_file'] ? $config['log_file'] : $this->logFile; | |
$this->maxLogFileSize = $config['max_log_file_size'] ? $config['max_log_file_size'] : $this->maxLogFileSize; | |
$this->cleanOldFiles = $config['clean_old_files']; | |
$this->maxLogFileArchive = $config['max_log_file_archive'] ? $config['max_log_file_archive'] : $this->maxLogFileArchive; | |
$this->logBacktrace = $config['clean_old_files']; | |
} | |
/** | |
* Writes info | |
* @param $data | |
*/ | |
public function info($data) | |
{ | |
$this->write($data, self::INFO); | |
} | |
/** | |
* Writes warning | |
* @param $data | |
*/ | |
public function warning($data) | |
{ | |
$this->write($data, self::WARNING); | |
} | |
/** | |
* Writes error | |
* @param $data | |
*/ | |
public function error($data) | |
{ | |
$this->write($data, self::ERROR); | |
} | |
/** | |
* Writes data to a proper file with the given log type. | |
* | |
* @param $data | |
* @param $type | |
*/ | |
private function write($data, $type) | |
{ | |
if ($this->isReachedMaxFileSize()) { | |
$this->shiftFileNames(); | |
} | |
$backtrace = ""; | |
if ($this->logBacktrace) { | |
$dbbt = debug_backtrace(); | |
$backtrace = " - <Called in " . $dbbt[1]['file'] . " at line " . $dbbt[1]['line'] . ">"; | |
} | |
$logLine = "[" . $type . "] - " . date('d.m.Y, l, @ H:i:s') . " - " . $data . $backtrace .PHP_EOL; | |
file_put_contents($this->logFile, $logLine, FILE_APPEND); | |
$this->cleanOldFiles(); | |
} | |
/** | |
* Checks if number of lines limit is reached | |
* Thanks and explanation: | |
* @see http://stackoverflow.com/questions/2162497/efficiently-counting-the-number-of-lines-of-a-text-file-200mb | |
* | |
* @return bool | |
*/ | |
private function isReachedMaxFileSize() | |
{ | |
$lineCount = 0; | |
try{ | |
$handle = fopen($this->logFile, "r"); | |
// this should throw warning, but if that is off check if handle is | |
// false, and if it is throw an exception manually | |
if (!$handle) { | |
throw new \Exception(); | |
} | |
} catch (\Exception $e) { | |
// break log file path to peaces, remove file name to get folder path | |
// check if folder exists, and create it if not | |
$path = explode(DIRECTORY_SEPARATOR, $this->logFile); | |
unset($path[count($path)-1]); | |
$path = implode(DIRECTORY_SEPARATOR, $path); | |
if (!file_exists($path)) { | |
mkdir($path); | |
} | |
touch($this->logFile); | |
$handle = fopen($this->logFile, "r"); | |
} | |
while(!feof($handle)){ | |
$line = fgets($handle, 4096); | |
$last = strlen($line) - 1; | |
if ($line[ $last ] == "\n" || $line[ $last ] == "\r") { | |
$lineCount++; | |
} | |
} | |
fclose($handle); | |
return $lineCount >= $this->maxLogFileSize; | |
} | |
/** | |
* When line number limit is reached we need to create archive files | |
* named simple_logger.log[x] where x is number of archive in order. Greater | |
* the number older the archive. | |
*/ | |
private function shiftFileNames() | |
{ | |
$existingFiles = glob($this->logFile . "*"); | |
$totalNo = count($existingFiles); | |
for ($i = $totalNo; $i > 1; $i--) { | |
$oldNo = $i - 1; | |
rename($this->logFile . $oldNo, $this->logFile . $i); | |
} | |
// rename current active | |
rename($this->logFile, $this->logFile . 1); | |
// create new log file | |
touch($this->logFile); | |
} | |
/** | |
* Clean old archive files. This can help prevent filling the disk with old log data. | |
*/ | |
private function cleanOldFiles() | |
{ | |
if (!$this->cleanOldFiles) { | |
return; | |
} | |
$existingFiles = glob($this->logFile . "*"); | |
// we need to subtract 1 because it counts active log as well | |
// and that means there is one more file that we must not take | |
$totalNo = count($existingFiles) - 1; | |
if ($totalNo <= $this->maxLogFileArchive) { | |
return; | |
} | |
for ($i = $totalNo; $i > $this->maxLogFileArchive; $i--) { | |
unlink($this->logFile . $i); | |
} | |
return; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment