【原创】yii2配置各种监控日志发送邮件及时处理

yii2日志自动发送邮件网上已经有很多例子了,这里会把踩坑和别的说说。

同样先把基本的说说,先配置项目公用邮箱配置common/config/main-local.php,自己用qq邮箱开通smtp就可以了。

'components' => [
   'db' => [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
      'username' => 'root',
      'password' => 'root',
      'charset' => 'utf8',
   ],
   'mailer' => [
      'class' => 'yii\swiftmailer\Mailer',
      'viewPath' => '@common/mail',
      // send all mails to a file by default. You have to set
      // 'useFileTransport' to false and configure a transport
      // for the mailer to send real emails.
      //if ($this->useFileTransport) {
      // $isSuccessful = $this->saveMessage($message);
      //} else {
      // $isSuccessful = $this->sendMessage($message);
      //}
      'useFileTransport' => false,//这句一定有,false发送邮件,true只是生成邮件在runtime文件夹下,不发邮件
      'transport' => [
         'class' => 'Swift_SmtpTransport',
         'host' => 'smtp.qq.com',  //每种邮箱的host配置不一样
         'username' => 'admin@netpc.com.cn',
         'password' => 'xxx',
         'port' => '465',
         'encryption' => 'ssl',
      ],
      'messageConfig' => [
         'charset' => 'UTF-8',
         'from' => ['admin@netpc.com.cn' => 'admin']
      ],
   ],
],

以上配置成功后就能发送邮件了,

$mail= Yii::$app->mailer->compose();
$mail->setTo('admin@netpc.com.cn');
$mail->setSubject($title);
//$mail->setTextBody('text');   //发布纯文字文本
$mail->setHtmlBody("<br>商品:<a href='".$url."' target='_blank'>地址</a>");    //发布可以带html标签的文本
if($mail->send())
   return "success";
else
   return "failse";

这样只是自己能发邮件,但是日志错误是不会自动发送的,这时候需要配置项目内容,这里用api项目举例,文件api/config/main.php。

'log' => [
   'traceLevel' => YII_DEBUG ? 3 : 0,
   //'flushInterval' => 1,
   'targets' => [
      [
         //'class' => 'yii\log\EmailTarget',//默认邮件处理类
         'class' => 'api\components\EmailTargetKen',//自定义日志处理类
         //'levels' => ['error', 'warning', 'trace', 'info'],//各种等级区分,根据需要使用
         'levels' => ['error'],
         'categories' => ['email_log'],
         'mailer' => 'mailer',
         'message' => [
            'from' => ['admin@netpc.com.cn' => 'admin'],
            'to' => ['admin@netpc.com.cn'],
            'subject' => 'Log message',

         ],
         'except' => ['yii\web\HttpException:404'],  // 排除404,不然的话你会发现你的邮箱里全塞满了这些邮件
         'exportInterval' => 1,//阀值一个错误的时候就执行输出
         'logVars' => [],
      ],
      [
         'class' => 'yii\log\FileTarget',//默认文件处理类
         'levels' => ['error', 'warning'],
         'exportInterval' => 1,
         'categories' => ['myinfo'],
         //'categories' => ['yii\*'],//$categories the message categories to filter by. If empty, it means all categories are allowed.
         'logVars' => ['*'],//记录最基本的 []赋值也可以
         //'logFile' => '@runtime/logs/order.log'.date('Ymd'),//用日期方式记录日志
      ],
   ],
],

这里说说坑了,假如你配置了categories这个属性,那么只有在自己代码里面执行Yii::error这样代码才能触发文件记录和发送邮件错误日志,而且是必需程序能正常完全执行完毕才能触发,例如代码有个语法输错array(少了一个括号,有没有配置一个全局没有categories分类的日志配置,那么以下Yii::error的日志都不会被触发,除非加多一个没有categories的全局配置。

Yii::error('error_test1');
Yii::error('error_test2','myinfo');//只会记录到myinfo分类文件日志里
Yii::error('error_test3','email_log');//只会记录到email_log分类邮件日志里

我就是按照网上配置了categories这个属性,结果没有用YII:error去触发错误,一直都没办法查看到日志和邮件。

我建议如果你需要分类保存日志,也需要配置一个全局的,因为只有全局没有限制分类的存在才能记录到所有的错误,那怕你没有配置分类,也能传分类参数用分类记录日志。

接下来说说api\components\EmailTargetKen这个自定义处理类,看看源码包括数据库记录什么都可以自己搞出来加工处理整合在一起。

我为什么做处理是因为在做测试的时候,故意写错语法,界面提示{“name”:”PHP Parse Error”,”message”:”syntax error, unexpected ‘]'”,”code”:4,”type”:”yii\\base\\ErrorException”,”file”:后面省略,可是日志文件里面却记录的不一样,少了”name”:”PHP Parse Error”这句语法错误提示,翻看源码后发现记录和提示的确是不一样。所以只能自己加工了。

namespace api\components;
public function export()
{
    // moved initialization of subject here because of the following issue
    // https://github.com/yiisoft/yii2/issues/1446
    if (empty($this->message['subject'])) {
        $this->message['subject'] = 'Application Log';
    }

    $error = Yii::$app->errorHandler->exception;
    $messages = array_map([$this, 'formatMessage'], $this->messages);

    //不喜欢它70个字符截断换行的方式    
    //$body = wordwrap(implode("\n", $messages), 70);
    //如果捕获的到错误就加上错误名称
    if($error){
        $body = $error->getName().implode("\n", $messages);
    }else{
        $body = implode("\n", $messages);
    }
    $message = $this->composeMessage($body);
    if (!$message->send($this->mailer)) {
        throw new LogRuntimeException('Unable to export log through email!');
    }
}

这样就能带上错误名称,有名称一看提示就能清楚大概是什么问题导致的。

yii2自动发送错误日志邮件有什么问题给我留言。

此条目发表在服务器分类目录,贴了标签。将固定链接加入收藏夹。

发表评论