Location: PHPKode > scripts > Log checker > log_checker.class.php
<?php
/** 
 * Description
 * 
 * This file contains functions required for crawling trought directories and filtering out 
 * files with extensions passed in array as parameter.
 * Script at first crawls trought directory passed as parameter. When it finds subdirectory, it will be craweled too though.
 * After matching all files by extension, files will be truncated to size defined as another parameter.
 * Log will be generated for all truncated files.
 *
 * Parameters:
 * - string [log file path (relative or absolute)]
 * - mixed  [directory/ies to crawl(can be string or array of paths)]
 * - mixed  [extension/s (can be string or array of extensions)]
 * - string [size limit of file] 
 * 
 * Notes:
 * - log files are generated in windows format (new line is specified by \r\n)
 * - all paths in example are relative to position of original script file log_checker.php
 * - limit size of file should be specified in following format, or error will be generated:
 * 	[float_number][K|M|G|Kb|KB|Mb|MB|Gb|GB] - first character defining K - kilo, M - mega or G - giga is not case sensitive, however optional second character "b" or "B" is case sensitve ("b" means limit / 8)
 * - if no second character in limit si specified, automaticaly assuming "B" - bytes
 * - first character must be specified, else error will be generated
 *
 * Usage example:
 * - if found files are larger than limit size, they will be truncated from beginning to target size. Note, that files will be truncated by lines, not by characters, so specified size could be a bit less or more (there is defined constant that should handle how smaller/bigger truncated file could be [default oscilation value is 1024B = 1kB])
 * 
 * @name Log Checker
 * @version v0.01
 * @author Peter Pivarc <hide@address.com>
 */

/**
 * constant AROUND
 * 
 * specifies, how many bytes could final filesize differs from desired size, because logs are handled by lines, not by characters
 *
*/
define("AROUND", 1024);


/**
 * Class log_checker
 * 
 */
class log_checker {

	
	/**
	 * Method will crawl directory and save path to files
	 * 
	 * Method crawls trought directory and calls itself recursively to catch all subdirectories
	 * it writes to array path to files, that match desired filetypes
	 *
	 * @access protected
	 * @param array &$to_save all paths are stored in this array
	 * @param string|array $dir directory or array of directories that should be checked
	 * @param string|array $log_file_extension file extension in which logs are stored
	 */
	function shorten_log_files(&$to_save, $dir, $log_file_extension = '.log'){

		$dh = opendir($dir);
		$paths = array();
		while (false !== ($filename = readdir($dh))) {
			$paths[] = $filename;
		}

		foreach ($paths as $file){
			if(is_dir($dir . "/" . $file)  && $file != "." && $file != ".."){
				$this->shorten_log_files(&$to_save, $dir . "/" . $file, $log_file_extension);
			}

			if(is_array($log_file_extension)){
				foreach ($log_file_extension as $ext){
					if(substr($dir. "/" . $file,-1*strlen($ext)) == $ext){
						$to_save[] = $dir . "/" . $file;
						break;
					}
				}
			}
			elseif(!empty($log_file_extension) && substr($file,-1*strlen($log_file_extension)) == $log_file_extension){
				$to_save[] = $dir . "/" . $file;
			}
			elseif(empty($log_file_extension)){
				$to_save[] = $dir . "/" . $file;
			}
		}
		closedir($dh);
	}

	/**
	 * This method will shorten file
	 * 
	 * it deletes n-lines from begining of the file, if file is bigger than condition specified
	 * log is generated about all actions
	 *
	 * @access protected
	 * @param string $path path to file
	 * @param float $limit size in bytes - maximal file size
	 * @param string $logfilename name of logfile where to write 
	 * @return boolean true if file is smaller than limit or process of truncating was successful, false if could not open file
	 */
	function shorten_file($path, $limit, $logfilename){
		$size = filesize($path);

		if($size >= $limit){
			$out = file($path);
			$total = 0;
			for($x = count($out) - 1; $x >= 0; $x --){
				$total += strlen($out[$x]);
				if($total >= ($limit - AROUND))
				break;
			}
			if(!$fp = fopen($path,'wb')){
				error_log(date("H:i:s d.m.Y"). " Failed to open file for writing binary, exiting.\r\n", 3, $logfilename);
				return false;
			}
			for($x; $x < count($out); $x ++){
				fwrite($fp, $out[$x]);
			}
			fclose($fp);
			clearstatcache();
			$sz = filesize($path);
			error_log(date("H:i:s d.m.Y"). " Truncating file $path. Size was $size bytes. New size is $sz bytes.\r\n", 3, $logfilename);
			return true;
		}
		return true;
	}


	
	/**
	 * Method will provide php5 function microtime(true);
	 *
	 * @access public
	 * @return float time in seconds
	 */
	function microtime_float()
	{
		list($usec, $sec) = explode(" ", microtime());
		return ((float)$usec + (float)$sec);
	}

	/**
	 * Method will initialize functions for directory processing
	 * 
	 * If path is passed as array, method will call itself recursively
	 *
	 * @access public
	 * @param string $logfilename name of log file that will be filled with action log
	 * @param string|array $foldertoscan path to directories to scan
	 * @param string|array $matchfiles only files with extension specified here will be processed
	 * @param string $limit all found files will be shortened to this size
	 * @return boolean false if error occurs
	 */
	function init($logfilename, $foldertoscan, $matchfiles, $limit){
		$fils = array();

		if(is_array($foldertoscan)){
			foreach ($foldertoscan as $folder){
				$this->init($logfilename, $folder, $matchfiles, $limit);
			}
			return true;
		}

		error_log(date("H:i:s d.m.Y"). " Starting scan process. Folder \"$foldertoscan\"\r\n", 3, $logfilename);
		$t1 = $this->microtime_float();
		$this->shorten_log_files(&$fils, $foldertoscan, $matchfiles);
		$t2 = $this->microtime_float();
		$num_files = count($fils);
		$t = $t2 - $t1;
		error_log(date("H:i:s d.m.Y"). " Finished scan process. Total time required: $t seconds. Found $num_files files matching search criteria.\r\n", 3, $logfilename);



		$fl = floatval($limit);

		$subject = $limit;
		$pattern = "[bBkKmMgG]{1,2}";
		ereg($pattern, $subject, $matches);
		$str = $matches[0];

		if(empty($str)){
			error_log(date("H:i:s d.m.Y"). " Exiting. Found limit format mismatch\r\n", 3, $logfilename);
			return false;
		}
		$str1 = substr($str, 0, 1);
		switch($str1){
			case "k":
			case "K":
				$limit = $fl * 1024;
				break;
			case "m":
			case "M":
				$limit = $fl * 1024 * 1024;
				break;
			case "g":
			case "G":
				$limit = $fl * 1024 * 1024 * 1024;
				break;
			default:
				error_log(date("H:i:s d.m.Y"). " Unable to determine filesize limit. Unknown format specified. Exiting...\r\n\r\n", 3, $logfilename);
				return false;
		}
		if(strlen($str) > 1 && substr($str,1, 1) == "b")
		$limit = $limit / 8;

		error_log(date("H:i:s d.m.Y"). " Starting truncate process. File size limit is $subject. Assuming that $subject equals to $limit bytes\r\n", 3, $logfilename);

		$t1 = $this->microtime_float();
		foreach($fils as $fname){
			$this->shorten_file($fname, $limit, $logfilename);
		}
		$t2 = $this->microtime_float();
		$tm = $t2 - $t1;

		error_log(date("H:i:s d.m.Y"). " Finished truncate process. Time required was $tm seconds\r\n\r\n", 3, $logfilename);
	}
}
?>
Return current item: Log checker