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() 所标注的方法。