Logger.php 6.63 KB
<?php
/**
 * Logger Class
 *
 * This is an application logging class.
 *
 * @author
 * https://findnerd.com/list/view/Logger-class-in-PHP/1852/
 *
 * adjustment by irul @ 20240831
 */

define("DATESTRING_FULL", "Y-m-d H:i:s");

class Logger
{
    private static $logger = null; // Instance of the logger class when default log file is in use.
    private static $user_logger = null; // Instance of the logger class when a log file is specified by the developer.
    private $user_handle = false; // Flag to determine which log file to use.
    private $log_handle = null; // Handle to the default log file.
    private $_user_log_handle = null; // Handle to the developer specified log file.

    private static $log_level = null; // The maximum level of logging to write to logs
    private static $log_level_integers = [
        'debug' => 8,
        'info' => 7,
        'warn' => 5,
        'error' => 4
    ]; // Map logging levels to syslog specifications, there's room for the other levels

    /**
     *  This method checks if there is an instance available. If yes it returns its handle otherwise
     *  create a new instance and return it's handle.
     *
     *  @param  string  $file
     *
     *     @return Object  Current instance of the class.
     *
     *     @access public
     *
     *     @static
     * */
    public static function get_logger($log_path = null, $log_file = null, $log_level = 'debug')
    {
        self::$log_level = ($log_level == 'warning') ? 'warn' : $log_level;
        if (is_null($log_path)) {
            if (!(isset(self::$logger)) || (is_null(self::$logger))) {
                self::$logger = new self();
            }
            return self::$logger;
        } else {
            if (!(isset(self::$user_logger)) || (is_null(self::$user_logger))) {
                self::$user_logger = new self($log_path, $log_file);
            }
            self::$user_logger->user_handle = true;
            return self::$user_logger;
        }
    }

    /*
     * This constructor checks if a log file exits with current date, if yes opens it,
     * if not create it and then opens its to write logs.
     *
     * @access private
     * */
    private function __construct($log_path = null, $log_file = null)
    {
        if (is_null($log_file)) {
            $log_file = date('Y-m-d');
        }
        if (is_null($log_path)) {
            $default_log_path = __DIR__ . '/logs';
            if (!is_dir($default_log_path)) {
                mkdir($default_log_path);
            }
            $log_file_name = $default_log_path . '/' . $log_file . '.log';
            $this->log_handle = fopen($log_file_name, 'a');
        } else {
            if (!is_dir($log_path)) {
                mkdir($log_path, 0777, true);
            }
            $log_file_name = $log_path . '/' . $log_file . '.log';
            $this->user_log_handle = fopen($log_file_name, 'a');
        }
    }

    /*
     * This method writes the log messages to the log file. This method internally calls the
     * do_write method to do the actual write operation.
     *
     * @param   string  $string    The log message to be written in the log file.
     *
     * $access public
     * */
    public function log($string)
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = call_user_func_array("Logger::get_message", func_get_args());
        $this->do_write($log_string, $log_source, "info");
    }

    /* Log Debug */
    public function debug($string)
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = call_user_func_array("Logger::get_message", func_get_args());
        $this->do_write($log_string, $log_source, "debug");
    }

    /* Log Info */
    public function info($string)
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = call_user_func_array("Logger::get_message", func_get_args());
        $this->do_write($log_string, $log_source, "info");
    }

    /* Log Warning */
    public function warning($string)
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = call_user_func_array("Logger::get_message", func_get_args());
        $this->do_write($log_string, $log_source, "warn");
    }

    /* Log Error */
    public function error($string)
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = call_user_func_array("Logger::get_message", func_get_args());
        $this->do_write($log_string, $log_source, "error");
    }

    /* Format Message */
    private function get_message($string) {
        $args = func_get_args();
        if (count($args) > 1) {
            array_shift($args);
            $message = vsprintf($string, $args);
        } else {
            $message = $string;
        }
        return $message;
    }

    /*
     * This method writes the array or dump with a messages to the log file. This method internally
     * calls the do_write method to do the actual write operation.
     *
     * @param   mixed   $var_name   The variable or dump to be written in the log file.
     * @param   string  $string    The log message to be written in the log file, defaults to VARDUMP.
     *
     * $access public
     * */
    public function dump($var_name, $string = '')
    {
        $log_source = sprintf("%s:%d", basename(debug_backtrace()[0]['file']), debug_backtrace()[0]['line']);
        $log_string = (empty($string) ? 'VARDUMP ' : 'Dump of ') . $string . ' => ' . var_export($var_name, true);
        $this->do_write($log_string, $log_source);
    }

    /*
     * This method is always called by the log() or dump() method. It writes the passed string
     * to the appropriate log file based on the object it is called upon.
     *
     * @param   string  $log_string    The log message to be written in the log file.
     *
     * $access public
     * */
    public function do_write($log_string, $log_source, $log_level = 'debug')
    {
        date_default_timezone_set('Asia/Jakarta');
        if (self::$log_level_integers[$log_level] > self::$log_level_integers[self::$log_level]){
            return;
        }
        $log_string = sprintf("%s [%s] %s -- %s", date(DATESTRING_FULL),  str_pad(strtoupper($log_level), 5), $log_string, $log_source);
        $log_string = $log_string . PHP_EOL;

        if ($this->user_handle) {
            fwrite($this->user_log_handle, $log_string);
        } else {
            fwrite($this->log_handle, $log_string);
        }
    }
}