Help us understand the problem. What is going on with this article?

【CodeIgniter】プロファイラを外部ファイル出力できるようにする

More than 1 year has passed since last update.

はじめに

この記事は CodeIgniter Advent Calendar 2017 4日目です。
3日目の記事は@NEKOGETさんの『CodeIgniterの歴史』でした。

■ プロファイラって?

アプリケーションのプロファイリング

早い話が下の画像のように、よさげな情報を画面下部に出力するものです。

pro.png

ですが画面下部に出力するとなると、ダイアログとかリダイレクトとか絡んできたとき、取り回しが悪くなります。

■ プロファイラを外部ファイル出力できるようにする

1)constantsに定数を追記する

/application/config/config.php
defined('PROFILER_DISABLE')         OR define('PROFILER_DISABLE', 0);
defined('PROFILER_OUTPUT_INTERNAL') OR define('PROFILER_OUTPUT_INTERNAL', 1);
defined('PROFILER_OUTPUT_EXTERNAL') OR define('PROFILER_OUTPUT_EXTERNAL', 2);

2)configに設定項目を追記する

/application/config/constants.php
/*
 * デバッグ用:プロファイラの出力モード切替
 * 
 * PROFILER_DISABLE         : 出力しない
 * PROFILER_OUTPUT_INTERNAL : 画面上に出力する
 * PROFILER_OUTPUT_EXTERNAL : 外部ファイル上に出力する
 */
$config['profiler_mode'] = PROFILER_OUTPUT_EXTERNAL;
$config['profiler_external_path'] = FCPATH . 'application/logs';

3)CI_Controllerクラスを継承して__construct()を変更する

※プロファイラを出力したいコントローラはextends MY_Controllerしてください。

/application/core/MY_Controller.php
<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Controller extends CI_Controller {

  public function __construct()
  {
    parent::__construct();
    if ($this->config->item('profiler_mode') !== PROFILER_DISABLE) {
      $this->output->enable_profiler(true);
    }
  }

}

4)CI_Profilerクラスを継承して表題のことができるようにあれこれする

※Codeigniterのバージョンによっては、CI_Profilerに記述されている関数のアクセス修飾子が private になっていたりするので注意してください。

/application/libraries/MY_Profiler.php
<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Profiler extends CI_Profiler {

  private $total_execution_time = 0;

  protected function _compile_benchmarks()
  {
    $output = parent::_compile_benchmarks();
    $matches = array();
    if (preg_match('/Total Execution Time.*(\d+\.\d+)/', trim(html_entity_decode(strip_tags($output))), $matches) === 1 && isset($matches[1])) {
      $this->total_execution_time = $matches[1];
    }
    return $output;
  }

// --------------------------------------------------------------------

  protected function _compile_memory_usage()
  {
    $this->CI->load->helper('number');
    $usage = memory_get_usage();
    $output = str_replace('</div></fieldset>', '', parent::_compile_memory_usage());
    $output .= ' (' . ($usage !== '' ? byte_format($usage) . ' / ' . ini_get('memory_limit') : $this->CI->lang->line('profiler_no_memory')) . ')'
            . '</div></fieldset>';
    return $output;
  }

// --------------------------------------------------------------------

  public function run()
  {
    $output = parent::run();
    if ($this->CI->config->item('profiler_mode') !== PROFILER_OUTPUT_EXTERNAL) {
      return $output;
    }
    $profiler_file_name = $this->generate_profiler_file_name();
    file_put_contents($profiler_file_name, $output);
  }

// --------------------------------------------------------------------

  private function generate_profiler_file_name()
  {
    $external_path = $this->CI->config->item('profiler_external_path');
    $controller_name = $this->CI->router->fetch_class();
    $now = $this->fetch_now('Ymd_His_u');
    $execution_time = ceil($this->total_execution_time * 1000);
    return "{$external_path}/{$controller_name}_{$now}({$execution_time}ms).html";
  }

// --------------------------------------------------------------------

  private function fetch_now($format)
  {
    return \DateTime::createFromFormat('U.u', sprintf('%6F', microtime(true)))
                    ->setTimezone(new \DateTimeZone(ini_get('date.timezone')))
                    ->format($format);
  }

}

※_compile_memory_usage()は、外部ファイル出力には関係していないので、必要なければ省略してください。
省略しないと MEMORY USAGE 部分が 485,656 bytes (474.0 KB / 2048M) みたく表示されるようになるので、個人的に捗ります。

5)画面を再読み込みしてプロファイラが外部ファイル出力されているか確認する

# ll /path/to/application/logs/
total 18
-rwxrwxrwx. 1 root root   131 Dec  4 10:26 index.html
-rwxrwxrwx. 1 root root 17329 Dec  4 10:44 welcome_20171204_104444_758158(40ms).html

welcome_20171204_104444_758158(40ms).html をブラウザで開くと、プロファイラ部分を閲覧することができます。

※プロファイラの外部ファイル出力を有効にすると、恐ろしい勢いで容量を逼迫させるので注意してください。
※この記事の記述はCodeigniterのスタイルガイドに沿っていません。phpdocがないのもごめんなさい。。。

おわり!

rhap
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした