ホームページ > バックエンド開発 > PHPチュートリアル > PHPのYiiフレームワークにおけるロギング機能について

PHPのYiiフレームワークにおけるロギング機能について

不言
リリース: 2023-04-01 13:48:02
オリジナル
1982 人が閲覧しました

この記事では、PHP の Yii フレームワークのログを中心に紹介します。ログの分析は、Web サイトの日常メンテナンスの基礎になります。Yii は、それを必要とする友人が参照できるようにします。

Yii ページレベルのログを有効にする

Main.php にログ セクションを追加します。
以下のページ ログ配列を表示します ('class'=>'CWebLogRoute', 'levels'=> 'trace ', //レベルはトレースです 'categories'=>'system.db.*' //データベース接続、データベース実行ステートメントなど、データベースに関する情報のみを表示します)、
は次のとおりです:

'log'=>array(
    'class'=>'CLogRouter',
    'routes'=>array(
      array(
        'class'=>'CFileLogRoute',
        'levels'=>'error, warning',

      ),
              // 下面显示页面日志 
              array( 
               'class'=>'CWebLogRoute', 
               'levels'=>'trace',  //级别为trace 
               'categories'=>'system.db.*' //只显示关于数据库信息,包括数据库连接,数据库执行语句 
              ), 
      // uncomment the following to show log messages on web pages
      /*
      array(
        'class'=>'CWebLogRoute',
      ),
      */
    ),
  ),
ログイン後にコピー

#Yii2 に付属のログ コンポーネントを展開します

##

 <?php

/**
 * author   : forecho <caizhenghai@gmail.com>
 * createTime : 2015/12/22 18:13
 * description:
 */
namespace common\components;

use Yii;
use yii\helpers\FileHelper;

class FileTarget extends \yii\log\FileTarget
{
  /**
   * @var bool 是否启用日志前缀 (@app/runtime/logs/error/20151223_app.log)
   */
  public $enableDatePrefix = false;

  /**
   * @var bool 启用日志等级目录
   */
  public $enableCategoryDir = false;

  private $_logFilePath = &#39;&#39;;

  public function init()
  {
    if ($this->logFile === null) {
      $this->logFile = Yii::$app->getRuntimePath() . &#39;/logs/app.log&#39;;
    } else {
      $this->logFile = Yii::getAlias($this->logFile);
    }
    $this->_logFilePath = dirname($this->logFile);

    // 启用日志前缀
    if ($this->enableDatePrefix) {
      $filename = basename($this->logFile);
      $this->logFile = $this->_logFilePath . &#39;/&#39; . date(&#39;Ymd&#39;) . &#39;_&#39; . $filename;
    }

    if (!is_dir($this->_logFilePath)) {
      FileHelper::createDirectory($this->_logFilePath, $this->dirMode, true);
    }

    if ($this->maxLogFiles < 1) {
      $this->maxLogFiles = 1;
    }
    if ($this->maxFileSize < 1) {
      $this->maxFileSize = 1;
    }

  }
}
ログイン後にコピー

#次のように使用します

&#39;components&#39; => [
  &#39;log&#39; => [
    &#39;traceLevel&#39; => YII_DEBUG ? 3 : 0,
    &#39;targets&#39; => [
      /**
       * 错误级别日志:当某些需要立马解决的致命问题发生的时候,调用此方法记录相关信息。
       * 使用方法:Yii::error()
       */
      [
        &#39;class&#39; => &#39;common\components\FileTarget&#39;,
        // 日志等级
        &#39;levels&#39; => [&#39;error&#39;],
        // 被收集记录的额外数据
        &#39;logVars&#39; => [&#39;_GET&#39;, &#39;_POST&#39;, &#39;_FILES&#39;, &#39;_COOKIE&#39;, &#39;_SESSION&#39;,&#39;_SERVER&#39;],
        // 指定日志保存的文件名
        &#39;logFile&#39; => &#39;@app/runtime/logs/error/app.log&#39;,
        // 是否开启日志 (@app/runtime/logs/error/20151223_app.log)
        &#39;enableDatePrefix&#39; => true,
        &#39;maxFileSize&#39; => 1024 * 1,
        &#39;maxLogFiles&#39; => 100,
      ],
      /**
       * 警告级别日志:当某些期望之外的事情发生的时候,使用该方法。
       * 使用方法:Yii::warning()
       */
      [
        &#39;class&#39; => &#39;common\components\FileTarget&#39;,
        // 日志等级
        &#39;levels&#39; => [&#39;warning&#39;],
        // 被收集记录的额外数据
        &#39;logVars&#39; => [&#39;_GET&#39;, &#39;_POST&#39;, &#39;_FILES&#39;, &#39;_COOKIE&#39;, &#39;_SESSION&#39;,&#39;_SERVER&#39;],
        // 指定日志保存的文件名
        &#39;logFile&#39; => &#39;@app/runtime/logs/warning/app.log&#39;,
        // 是否开启日志 (@app/runtime/logs/warning/20151223_app.log)
        &#39;enableDatePrefix&#39; => true,
        &#39;maxFileSize&#39; => 1024 * 1,
        &#39;maxLogFiles&#39; => 100,
      ],
      /**
       * info 级别日志:在某些位置记录一些比较有用的信息的时候使用。
       * 使用方法:Yii::info()
       */
      [
        &#39;class&#39; => &#39;common\components\FileTarget&#39;,
        // 日志等级
        &#39;levels&#39; => [&#39;info&#39;],
        // 被收集记录的额外数据
        &#39;logVars&#39; => [&#39;_GET&#39;, &#39;_POST&#39;, &#39;_FILES&#39;, &#39;_COOKIE&#39;, &#39;_SESSION&#39;,&#39;_SERVER&#39;],
        // 指定日志保存的文件名
        &#39;logFile&#39; => &#39;@app/runtime/logs/info/app.log&#39;,
        // 是否开启日志 (@app/runtime/logs/info/20151223_app.log)
        &#39;enableDatePrefix&#39; => true,
        &#39;maxFileSize&#39; => 1024 * 1,
        &#39;maxLogFiles&#39; => 100,
      ],
      /**
       * trace 级别日志:记录关于某段代码运行的相关消息。主要是用于开发环境。
       * 使用方法:Yii::trace()
       */
      [
        &#39;class&#39; => &#39;common\components\FileTarget&#39;,
        // 日志等级
        &#39;levels&#39; => [&#39;trace&#39;],
        // 被收集记录的额外数据
        &#39;logVars&#39; => [&#39;_GET&#39;, &#39;_POST&#39;, &#39;_FILES&#39;, &#39;_COOKIE&#39;, &#39;_SESSION&#39;,&#39;_SERVER&#39;],
        // 指定日志保存的文件名
        &#39;logFile&#39; => &#39;@app/runtime/logs/trace/app.log&#39;,
        // 是否开启日志 (@app/runtime/logs/trace/20151223_app.log)
        &#39;enableDatePrefix&#39; => true,
        &#39;maxFileSize&#39; => 1024 * 1,
        &#39;maxLogFiles&#39; => 100,
      ],
    ],
  ],
],
ログイン後にコピー

##Yii ログ ロジック

Yii は階層型ログ処理メカニズムを使用します。つまり、ログ収集とログの最終処理 (図のように、ファイルへの保存、データへの保存) は分離されています。

ログ情報の収集は CLogger (ログレコーダー) によって完了し、ログ情報の配布と処理は CLogRouter のスケジューリングに従って処理オブジェクト (CFileLogRoute やロギング ディレクトリ下の継承など) に分散されます (ログと呼ばれます)。ルーティングマネージャー) (ログプロセッサと呼ばれる CLogRoute クラスから) のソースコードを何度も読んだ後、Yii のこのような階層的な処理により柔軟な拡張が容易になる設計思想に感銘を受けました。

ログ情報は、通常情報、プロファイル、トレース、警告、エラーレベルなどのレベルに分かれています。たとえば、CFileRoute のレベル属性を設定すると、ログ情報のみを処理できます。指定されたレベル。

プログラムで呼び出された場合:
#

Yii::log($message,CLogger::LEVEL_ERROR,$category);
ログイン後にコピー


#対応するプロセスは次のようになります:

#CLogger インスタンスの生成

YII_DEBUG および YII_TRACE_LEVEL が有効な値として定義されており、ログ レベルがプロファイルではない場合、呼び出しトレースバック情報が生成され、ログ情報に追加されます。

  • CLogger::log($msg,$level,$category) を呼び出してログを収集します。実際、この時点ではログはファイルに書き込まれません。メモリに保存されます。

  • #質問: ログがファイルに書き込まれたのはいつですか?

    追跡を繰り返した結果、プロセッサ CLogRouter::processLogs() が、CLogRouter クラスの init メソッド内の Application オブジェクトの OnEndRequest イベントにバインドされていることがわかりました。同時に、イベント プロセッサーの CLogRouter::collectLogs メソッドも Yii::$_logger の onFlush イベントにバインドされます。これは、ログが多すぎる場合にログを更新し、タイムリーにファイルに書き込むために使用されます。 Yii::log() のメッセージ。コードは次のとおりです:
  • /**
     * Initializes this application component.
     * This method is required by the IApplicationComponent interface.  
    */
     public function init(){ 
      parent::init(); 
      foreach($this->_routes as $name=>$route) { 
        $route=Yii::createComponent($route);  
        $route->init();  
        $this->_routes[$name]=$route; 
      } 
      Yii::getLogger()->attachEventHandler(&#39;onFlush&#39;,array($this,&#39;collectLogs&#39;)); 
      Yii::app()->attachEventHandler(&#39;onEndRequest&#39;,array($this,&#39;processLogs&#39;));}
    ログイン後にコピー

CApplication::run() メソッドで定義されています:

 if($this->hasEventHandler(&#39;onEndRequest&#39;)) {
 $this->onEndRequest(new CEvent($this));
 }
ログイン後にコピー

この時点で、CLogger (Yii::$_logger) はログを収集する (コンテンツ構造に記録する) だけを行い、次の場所にある $app オブジェクトから CLogRouter を呼び出すことがわかります。ログ処理用の processLogs の終わり。 Yii は、ログの複数のルーティングをサポートしています。たとえば、同じログをファイルに書き込んだり、ページに表示したり、同時に電子メールで送信したり、同時にデータベースに記録したりすることもできます。構成ファイル内のログ: Routes 構成は、複数のルート分散を実現するために log:routes の複数の要素を構成することによって実装されます。ログ情報のフィルタリングと記録は、最終的なログ プロセッサによって処理されます。

ログ プロセッサによって実行されるタスクには、主に次の点が含まれます。 CLogger からすべてのログを取得し、それらをフィルタリングします (主に、log:routes:levels/categories で定義されたレベルとカテゴリ)

最初にフィルタリングについて、CFileLogRoute::collectLogs() のロジックを参照してください:

 $logs=$logger->getLogs($this->levels,$this->categories); //执行过滤,只得到期望信息
ログイン後にコピー

ログのフィルタリングが完了しました。次のステップは、ログの最終処理を実行することです。 (ファイルへの書き込み、データベースへの記録など)


 CFileLogRoute::processLogs($logs);
ログイン後にコピー

しかし、この関数には小さなバグがあります。 CFileLogRoute は、Linux と同様のログ ローテーション機能 (LogRoate) を実装しており、ログ ファイルのサイズを規定しています。また、そこから学び、アイデアを吸収したいと思っています!

protected/config/main.php の構成:


&#39;preload&#39;=>array(&#39;log&#39;),
components => array(
       &#39;log&#39;=>array(
         &#39;class&#39;=>&#39;CLogRouter&#39;,
         &#39;routes&#39;=>array(
          array(
            &#39;class&#39;=>&#39;CFileLogRoute&#39;,
            &#39;levels&#39;=>&#39;error, warning,trace&#39;,
          ),
         )
        )
       )
ログイン後にコピー

定义log组件需要预先加载(实例化)。配置使用CLogRouter作为日志路由管理器,并设置了其日志路由处理器(routes属性)及其配置属性。而preload, log属性的定义,均要应用到CWebApplication对象上(请参阅CApplication::__construct中的configure调用, configure从CModule继承而来)。而在CWebApplication的构造函数中执行preloadComponents(),就创建了log对象(即CLogRouter的实例)。
创建并初始化一个组件时,实际上调用的是CModule::getComponent, 这个调用中使用YiiBase::createComponent创建组件对象,并再调用组件的init初始化之。
再阅读CLogRouter::init()过程,在这里有两个关键之处,一是创建日志路由处理器(即决定日志的最终处理方式:写入文件,邮件发送等等),二是给应用程序对象绑定onEndRequest事件处理CLogRouter::processLogs()。而在CApplication::run()确实有相关代码用于运行onEndRequest事件处理句柄:

 if($this->hasEventHandler(&#39;onEndRequest&#39;)) {
  $this->onEndRequest(new CEvent($this));
 }
ログイン後にコピー

也就是说,日志的最终处理(比如写入文件,系统日志,发送邮件)是发生在应用程序运行完毕之后的。Yii使用事件机制,巧妙地实现了事件与处理句柄的关联。
也就是说,当应用程序运行完毕,将执行CLogRouter::processLogs,对日志进行处理,。CLogRouter被称之为日志路由管理器。每个日志路由处理器从CLooger对象中取得相应的日志(使用过滤机制),作最终处理。
具体而言Yii的日志系统,分为以下几个层次:

日志发送者,即程序中调用Yii::log($msg, $level, $category),将日志发送给CLogger对象
CLogger对象负责将日志记录暂存于内存之中程序运行结束后,log组件(日志路由管理器CLogRoute)的processLogs方法被激活执行,由其逐个调用日志路由器,作日志的最后处理。

更为详细的大致过程如下:

  • CApplication::__construct()中调用preloadComponents, 这导致log组件(CLogRoute)被实例化,并被调用init方法初始化。

  • log组件(CLogRoute)的init方法中,其是初始化日志路由,并给CApplication对象onEndRequest事件绑定处理流程processLogs。给CLooger组件的onFlush事件绑定处理流程collectLogs。

  • 应用程序的其它部分通过调用Yii::log()向CLogger组件发送日志信息,CLogger组件将日志信息暂存到内存中。

  • CApplication执行完毕(run方法中),会激活onEndRequest事件,绑定的事件处理器processLogs被执行,日志被写入文件之中。 Yii的日志路由机制,给日志系统扩展带来了无限的灵活。并且其多道路由处理机制,可将同一份日志信息进行多种方式处理。

这里举出一个案例:发生error级别的数据库错误时,及时给相关维护人员发送电子邮件,并同时将这些日志记录到文件之中。规划思路,发送邮件和手机短信是两个不同的功能,Yii已经带了日志邮件发送组件(logging/CEmailLogRoute.php),但这个组件中却使用了php自带的mail函数,使用mail函数需要配置php.ini中的smtp主机,并且使用非验证发送方式,这种方式在目前的实际情况下已经完全不可使用。代替地我们需要使用带验证功能的smtp发送方式。在protected/components/目录下定义日志处理器类myEmailLogRoute,并让其继承自CEmailLogRoute,最主要的目的是重写CEmailLogRoute::sendEmail()方法 ,其中,SMTP的处理细节请自行完善(本文的重点是放在如何处理日志上,而不是发送邮件上)。
接下来,我们就可以定义日志路由处理,编辑protected/config/main.php, 在log组件的routes组件添加新的路由配置:

&#39;log&#39;=>array(
&#39;class&#39;=>&#39;CLogRouter&#39;,
&#39;routes&#39;=>array(
array(
&#39;class&#39;=>&#39;CFileLogRoute&#39;,
&#39;levels&#39;=>&#39;error, warning,trace&#39;,
),
array(
&#39;class&#39; => &#39;myEmailLogRoute&#39;,
&#39;levels&#39; => &#39;error&#39;, #所有异常的错误级别均为error, 
&#39;categories&#39; => &#39;exception.CDbException&#39;, #数据库产生错误时,均会产生CDbException异常。
&#39;host&#39; => &#39;mail.163.com&#39;,
&#39;port&#39; => 25,
&#39;user&#39; => &#39;jeff_yu&#39;,
&#39;password&#39; => &#39;you password&#39;,
&#39;timeout&#39; => 30,
&#39;emails&#39; => &#39;jeff_yu@gmail.com&#39;, #日志接收人。
&#39;sentFrom&#39; => &#39;jeff_yu@gmail.com&#39;,
),
ログイン後にコピー

经过以上处理,即可使之实现我们的目的,当然你可以根据自己的需要进一步扩展之。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Yii2框架实现数据库常用操作解析

关于yii2中结合gridview使用modal弹窗的代码

以上がPHPのYiiフレームワークにおけるロギング機能についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート