ログツールクラス


今日は自分でログツールを書きました。CIのLog.php、公式文書とhttp://hqlong.com/2009/01/530.html貴重なご意見をお願いします。
ダウンロード
ソース
<?php
date_default_timezone_set("Asia/ShangHai");
/**
  *      
  * 
  *     :
  * require 'LogUtil.php';
  * LogUtil::get_instance()->debug('debug msg');
  * output:
  * [2013-11-01 18:31:03][DEBUG][127.0.0.1][LogUtil.php:151][/LogUtil.php][debug msg]
  * [email protected]
  * 2013-11-01
  */
class LogUtil {

	private static $_instance;
	private $_log_dir = "./"; //     ,       
	private $_log_max_size = 1 << 30; //         ,  1G
    private $_log_max_num = 1; //     ,      1,        1

	private function __construct() {}

	public static function get_instance() {
		if (!isset(self::$_instance)) {
			$c = __CLASS__;
			self::$_instance = new $c;
		}

		return self::$_instance;
	}

	public function __clone(){
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

    public function free() {
    	self::$_instance = null;
    }

    public function debug($msg) {
    	$time = time();
        $log_name = $this->get_log_name($time);
        $this->check_file_size($time, $log_file);
    	$log_msg = $this->format_log_msg($msg, $time, "DEBUG");
    	$this->write_log($time, $log_name, $log_msg);
    }

    public function fatal($msg) {
    	$time = time();
        $log_name = $this->get_log_name($time);
        $this->check_file_size($time, $log_file);
    	$log_msg = $this->format_log_msg($msg, $time, "FATAL");
    	$this->write_log($time, $log_name, $log_msg);
    	$this->free();
    }

    public function warn($msg) {
    	$time = time();
        $log_name = $this->get_log_name($time);
        $this->check_file_size($time, $log_file);
    	$log_msg = $this->format_log_msg($msg, $time, "WARN");
    	$this->write_log($time, $log_name, $log_msg);
    }

    public function info($msg) {
    	$time = time();
        $log_name = $this->get_log_name($time);
        $this->check_file_size($time, $log_name);
    	$log_msg = $this->format_log_msg($msg, $time, "INFO");
    	$this->write_log($time, $log_name, $log_msg);
    }

	/**
	  *         
	  *       =    +   .log
	  *            
	  */
    private function get_log_name($time) {
        $seq_num = rand(1, $this->_log_max_num);
        return $this->_log_dir . date("Y-m-d", $time) . "-{$seq_num}.log";
    }
	
	/**
	  *        
	  */
    private function format_log_msg($msg, $time, $priority) {
    	$datetime = date("Y-m-d H:i:s", $time);
    	$priority = strtoupper(trim($priority));
    	$ip = get_user_ip();
    	$arr_trace = debug_backtrace();
    	$trace = end($arr_trace);
    	$file = basename($trace['file']);
    	$line = $trace['line'];
    	$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
    	return "[{$datetime}] [{$priority}] [{$ip}] [{$file}:{$line}] [{$uri}] [{$msg}]" . PHP_EOL;
    }
	
	/**
	  *           ,  1G         
	  *                
	  */
    private function check_file_size($time, $log_name) {
    	try {
    		if (file_exists($log_name) && filesize($log_name) >= $this->_log_max_size) {
		    	// if log size >= 1GB(default), 
		    	// then rename this file and make it readonly
		    	$rename_log_file = $this->_log_dir . date("Y-m-d H:i:s", $time) . '.log';
		    	rename($log_name, $rename_log_file);
		    	chmod($rename_log_file, 0444); //       
		    }
    	} catch (Exception $e) {
    		die('error accoured at ' . basename(__FILE__) . ':' . __LINE__ . " with msg : " . $e->getMessage());
    	}
    	
    }
	
	/**
	  *          
	  */
    private function write_log($time, $log_name, $log_msg = "") {
    	try {	    	
            if ($fp = fopen($log_name, 'a')) {
				//          ,1ms     ,    ;
				//   1ms         
                $start_time = microtime();
                do {
                    $lock = flock($fp, LOCK_EX);
                    if(!$lock) {
                        usleep(rand(10, 30000));
                    }
                } while ((!$lock) && ((microtime() - $start_time) < 1000));
                if ($lock) {
                  fwrite($fp, $log_msg);
                  flock($fp, LOCK_UN);
                }
                fclose($fp);
                chmod($log_name, 0666);
            } else {
                die("open {$log_name} failed at " . basename(__FILE__) . " line " . __LINE__);
            }
	    	clearstatcache();
    	} catch (Exception $e) {
    		die('error accoured at ' . basename(__FILE__) . ':' . __LINE__ . " with msg : " . $e->getMessage());
    	}
    }
}

/**
  *     ip
  */
function get_user_ip() {
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } elseif (isset($_SERVER['HTTP_CLIENTIP'])) {
        $ip = $_SERVER['HTTP_CLIENTIP'];
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif (getenv('HTTP_CLIENTIP')) {
        $ip = getenv('HTTP_CLIENTIP');
    } elseif (getenv('REMOTE_ADDR')) {
        $ip = getenv('REMOTE_ADDR');
    } else {
        $ip = '127.0.0.1';
    }

    $pos = strpos($ip, ',');
    if( $pos > 0 ) {
        $ip = substr($ip, 0, $pos);
    }

    return trim($ip);
}