不同的开发任务、不同的功能、模块,在开发期间应该用不同的文件或目录保存日志,可以把开启配置和目录文件配置合并成一个:
目录文件不为空,表示记录,且各个功能、模块的配置不一样。
如果为空,表示关闭业务逻辑日志。
这样每个功能模块在开发期间,定义一个临时的日志目录,专门保存该功能模块的日志。
同时也可以按需写入全局程序日志中
以Laravel为例:
日志目录配置
增加专用配置文件:
config/path.php
return [ 'test' => 'test', ];
调用:
slog('log', 'test'); // 仅仅记录log
slog('log', 'test', 1); // 记录log同时写入系统日志
slog('log', 'test', 0, 1); // 记录log,不写入系统日志,打印调用堆栈
实现代码:
/** * 业务逻辑日志 slog * @param string/mixed $str 记录的内容 * @param string $pathName,日志目录名称,在配置文件中 * @param int $sysLog 是否写入系统日志 * @param bool $backtrace 是否打印调用 * @return null */ // slog, super_log的简写形式 function slog($str, $pathName = '', $sysLog = 0, $backtrace = false){ if(empty($pathName)){ return false; } // 功能特性日志(业务逻辑日志) // $featureLogPath = C($pathName); $featureLogPath = config('path.'.$pathName); if(!$featureLogPath && !$sysLog){ return null; // 既不写入系统日志,也没有逻辑日志目录,直接退出 } // 调用位置: $backTraceArr = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // pf($backTraceArr); $trace1 = $backTraceArr[0]; $trace2 = $backTraceArr[1]; $function = $trace2['function']; // 兼容super_log调用 if($function == 'super_log'){ $trace1 = $backTraceArr[1]; $trace2 = $backTraceArr[2]; $function = $trace2['function']; } $file = $trace1['file']; $line = $trace1['line']; $class = isset($trace2['class']) ? $trace2['class'] : ''; $type = isset($trace2['type']) ? $trace2['type'] : ''; $function = $class.$type.$function; $logCall = $file.PHP_EOL.$function.', '.$line.PHP_EOL; if(!is_string($str)){ $str = print_r($str, 1); } $log = $logCall.$str; if($sysLog){ // 系统原有日志 // Log::write($log); Log::info($log); // need : use Log; } if($featureLogPath){ flog($log, 0, 0, $backtrace, $featureLogPath); } } if(!function_exists('flog')){ /** * 日志函数 * @param mixed $data 写入日志的数据,可以是字符串,可以是数组、对象 * @param int $filterSelect 记录数据库语句时,是否过滤select,默认0 不过滤 * @param int $stop 是否在记录日志后终止程序,默认0,不终止 * @param int $backTrace 打印调用堆栈,默认0,不打印 * @param string $subPath 日志保存子目录,默认为空 * @return string * */ function flog($data,$filterSelect=0, $stop=0, $backTrace=0, $subPath=''){ // 是否过滤select语句: if($filterSelect){ if(is_string($data)){ $patt = "/^SELECT/i"; if(preg_match($patt, $data)){ return "过滤select查询(不记录)"; } } } $path = get_logic_path(); // 为了提高适用性,无论目录结尾有无/或\,都去掉然后再加上: $path = rtrim($path,"/\\"); // 子目录 if(!empty($subPath)){ $path = $path.DIRECTORY_SEPARATOR.$subPath; if(!file_exists($path)){ if(!mkdir($path,0755,1)){ exit('创建子目录失败 '.$path); } } if(!is_writable($path)){ exit('子目录不可写 '.$path); } } $fileName = "test_".date("Y-m-d").".log"; $file = $path.DIRECTORY_SEPARATOR.$fileName; $data = print_r($data, 1); // 调用堆栈: if($backTrace){ if($backTrace == 1){ $backTraceArr = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); }else{ $backTraceArr = debug_backtrace(); } krsort($backTraceArr); $backTraceStr = print_r($backTraceArr, 1); $backTraceStr = PHP_EOL.PHP_EOL."调用堆栈:".PHP_EOL."$backTraceStr"; }else{ $backTraceStr = ""; } $res = "日志信息:".date("Y-m-d H:i:s").PHP_EOL.$data.$backTraceStr.PHP_EOL.PHP_EOL.PHP_EOL; file_put_contents($file, $res, FILE_APPEND); // 是否终止程序: if($stop){ exit; } } } // 获取业务逻辑日志目录(不存在就创建) function get_logic_path(){ // $path = APP_PATH; // $path = RUNTIME_PATH; // $path = LOG_PATH.'Logic'; // $appRoot = dirname(dirname(__DIR__)); // $logPath = $appRoot.DIRECTORY_SEPARATOR.'storage'.DIRECTORY_SEPARATOR.'logs'; $logPath = storage_path('logs'); $path = $logPath.DIRECTORY_SEPARATOR.'logic'; if(!file_exists($path)){ if(!mkdir($path)){ exit('创建逻辑日志目录失败'); } } if(is_writable($path)){ return $path; }else{ exit('日志目录('.$path.')不可写!'); } }