1.自定義 Debug 類
class Debug
{
//日誌顯示類型
const saveLogFile = true; //保存到文件
const viewOnConsole = true; //顯示在控制檯
/**
* @param string $name 函數名
* @param array $arguments 參數列表
*/
private static function log($name, $arguments){
$format = array_splice($arguments, 0, 1)[0];
if (self::viewOnConsole) {
$log = new CLog();
if(method_exists($log, $name))
CLog::$name($format, ...$arguments);
else
CLog::error('方法名(%s)不存在', $name);
}
if(self::saveLogFile){
$log = new Log();
if(method_exists($log, $name))
Log::$name($format, ...$arguments);
else
Log::error('方法名(%s)不存在', $name);
}
}
public function __call($name, $arguments){
self::log($name, $arguments);
}
public static function __callStatic($name, $arguments){
self::log($name, $arguments);
}
}
測試的時候 發現 生成的記錄 一直是在log 函數裏面調用的
2020/04/29-14:16:00 [INFO] App\Tcp\Miscellany\Debug:log(24) minute(0) task run: 2020-04-29 14:16:00
通過層層挖掘 發現swoft 的log 日誌的層級是通過debug_backtrace()
獲取的,然後發現一個有意思的代碼塊
public function getTrace(string $message): string
{
$stackStr = '';
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
$count = count($traces);
if ($count >= 6) {
$info = $traces[4];
if (isset($info['file'], $info['class'])) {
$class = $info['class'];
$lineNum = $traces[3]['line'];
$function = $info['function'];
$stackStr = sprintf('%s:%s(%s)', $class, $function, $lineNum);
}
}
if (!empty($stackStr)) {
$message = sprintf('%s %s', $stackStr, $message);
}
return $message;
}
果斷將 $traces[4] 改成了 $traces[6],感覺世界一片寧靜了
$info = $traces[6];
2020/04/29-14:34:24 [INFO] App\Tcp\Miscellany\TimerClass:minuteTask(24) minute(24) task run: 2020-04-29 14:34:24
沒高興一會兒,我又發現自己還是太年輕了,
2020/04/29-14:35:24 [INFO] App\Tcp\Miscellany\TimerClass:minuteTask(24) minute(24) task run: 2020-04-29 14:35:24
Fatal error: Uncaught ErrorException: Undefined offset: 6 in /var/www/swoft/vendor/swoft/log/src/CLogger.php:91
Stack trace:
#0 /var/www/swoft/vendor/swoft/log/src/CLogger.php(91): Swoft\Error\DefaultErrorDispatcher->handleError(8, 'Undefined offse...', '/var/www/swoft/...', 91, Array)
系統提示,還有 CLog 和Log 類直接調用的方法再使用,並且直接調用他們的時候,$traces 沒有6層調用,所以就得做如下變動
Clog 修改
namespace Swoft\Log\CLogger
90 $info = $traces[6]??$traces[4];
93 $lineNum = $traces[5]['line']??$traces[3]['line'];
public function getTrace(string $message): string
{
$stackStr = '';
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
$count = count($traces);
if ($count >= 6) {
$info = $traces[6]??$traces[4];
if (isset($info['file'], $info['class'])) {
$class = $info['class'];
$lineNum = $traces[5]['line']??$traces[3]['line'];
$function = $info['function'];
$stackStr = sprintf('%s:%s(%s)', $class, $function, $lineNum);
}
}
if (!empty($stackStr)) {
$message = sprintf('%s %s', $stackStr, $message);
}
return $message;
}
Log 修改內容
namespace Swoft\Log\Logger;
407 $info = $traces[5]??$traces[3];
if ($count >= 6) {
$info = $traces[6]??$traces[4];
if (isset($info['file'], $info['class'])) {
$class = $info['class'];
$lineNum = $traces[5]['line']??$traces[3]['line'];
$function = $info['function'];
$stackStr = sprintf('%s:%s(%s)', $class, $function, $lineNum);
}
}
這下是真的可以寧靜了
2020/04/29-14:36:57 [INFO] App\Tcp\Controller\ChengduDeviceController:deviceRtdData(288) 客戶端#1 編號(Y0028115200002) 上傳實時數據,內容爲:{"DataTime":1588142222,"W01":{"Avg":"0.0","Flag":"N"},"W02":{"Avg":"0","Flag":"N"},"T01":{"Avg":"0.0","Flag":"N"},"H01":{"Avg":"0.0","Flag":"N"},"PM25":{"Avg":"0","Flag":"N"},"PM10":{"Avg":"0","Flag":"N"},"B03":{"Avg":"0.0","Flag":"N"}}
2020/04/29-14:36:58 [INFO] App\Tcp\Miscellany\TimerClass:minuteTask(24) minute(58) task run: 2020-04-29 14:36:58
2.Crontab 使用
在swoft v2.0 文檔中有介紹
a. .env 文件中加入配置
CRONABLE=true
b. 註解類和註解定時方法
* @Scheduled()
* @Cron("0/2 * * * * *")
<定時小技巧>
- / * * * * * * 表示每秒執行一次。
- / 0 * * * * * 表示每分鐘的第0秒執行一次,即每分鐘執行一次。
- / 0 0 * * * * 表示每小時的0分0秒執行一次,即每小時執行一次。
- / 0/10 * * * * * 表示每分鐘的第0秒開始每10秒執行一次。
- / 10-20 * * * * * 表示每分鐘的第10-20秒執行一次。
- / 10,20,30 * * * * * 表示每分鐘的第10,20,30秒各執行一次。
b. 配置啓動方式
自啓動
return [
'httpServer' => [
// ...
'process' => [
'crontab' => bean(Swoft\Crontab\Process\CrontabProcess::class)
],
// ...
],
];
手動啓動
$crontab = BeanFactory::getBean("crontab");
$crontab->execute("testCrontab", "method");
通過 Bean 容器拿到 crontab 管理器,然後直接使用 execute($beanName,$methodName) 方法,此方法有兩個參數,$beanName 就是傳入在 @Scheduled() 註解中設置的名字,$methodName 則是傳入 @Scheduled() 標註的類中,@Cron() 所標註的方法。