LoginSignup
11
6

More than 5 years have passed since last update.

Laravel5.4 ログ周りの設定 1/3 開始・終了ログを残す

Last updated at Posted at 2017-06-17

ログ周りの設定レシピ、3品。今回はその1品目。

やりたいこと

アプリケーションの開始・終了ログを残すようにします。

  • 開始ログ:リクエストURLやバッチコマンドを出力
  • 終了ログ:処理時間・使用メモリのピーク値を出力
laravel.log
[2017-06-17 10:16:11] local.INFO: -- Startup {"method":"GET","uri":"/log/sample?a=1&b=2"} 
[2017-06-17 10:16:11] local.INFO: -- Shutdown {"time":"153.086[ms]","memory":"2048[kb]"} 
[2017-06-17 10:16:19] local.INFO: -- Startup {"command":"php artisan list"} 
[2017-06-17 10:16:19] local.INFO: -- Shutdown {"time":"383.189[ms]","memory":"6144[kb]"} 

環境

Laravel 5.4.25
PHP 7.1.3

実装手順

  1. アプリケーションの開始・終了ログを残すクラスを作成
  2. Kernelクラスのbootstrappersプロパティに作ったクラスを登録します。(登録するクラスにはbootstrapメソッドが必要です。)

以下、サンプル。
一応動作確認はしていますが、サンプルをそのまま使う場合は自己責任で。

開始・終了ログを残すクラス

app\Bootstrap\ApplicationLog.php
<?php

namespace App\Bootstrap;

use Illuminate\Contracts\Foundation\Application;

/**
 * include時の時間を取得しておく。
 */
if (!defined('APP_START_TIME')) {
    define('APP_START_TIME', microtime(true));
}

/**
 * アプリケーションログ設定クラス
 *
 * @package app.Bootstrap
 */
class ApplicationLog
{
    /**
     * 警告閾値:利用メモリ(MB)
     */
    const THRESHOLD_WARNING_MEMORY = 100;

    /**
     * The application instance.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $this->app = $app;

        // テスト時はアプリケーションログなし
        if (!$app->environment('testing')) {
            // シャットダウンハンドラ追加:シャットダウンログ
            register_shutdown_function([$this, 'handleShutdownLog']);

            // 起動ログ
            $this->startupLog();
        }
    }

    /**
     * 起動ログ
     */
    public function startupLog()
    {
        if ($this->app->runningInConsole()) {
            $command = sprintf('php %s', implode(' ', (array)array_get($GLOBALS, 'argv')));
            $params = compact('command');
        } else {
            $method = $_SERVER['REQUEST_METHOD'];
            $uri = $_SERVER['REQUEST_URI'];
            $params = compact('method', 'uri');
        }
        app('log')->info('-- Startup', $params);
    }

    /**
     * シャットダウンログ
     *
     * @return void
     */
    public function handleShutdownLog()
    {
        // シャットダウンログを出力
        $time = $this->getProcessingTime();
        $memory = $this->getPeekMemory();
        if ($this->isOverUsingMemory(self::THRESHOLD_WARNING_MEMORY)) {
            app('log')->warning('using a large amount of memory.', compact('memory'));
        }
        app('log')->info('-- Shutdown', compact('time', 'memory'));
    }

    /**
     * 単位をつけて見やすくした時間を返す
     *
     * @param float $time マイクロ秒数
     * @return string
     */
    protected function formatTime($time)
    {
        if ($time < 1) {
            return sprintf('%0.3f[ms]', $time * 1000);
        } else if ($time < (1 / 1000)) {
            return sprintf('%0.3f[μs]', $time * 1000 * 1000);
        }
        return sprintf('%0.3f[s]', $time);
    }

    /**
     * 単位をつけて見やすくしたメモリを返す
     *
     * @param float $value
     * @return string
     */
    protected function formatMemory($value)
    {
        if ($value < 1024 * 10) {
            // 10KBまではB表示
            return sprintf('%s[b]', $value);
        } else if ($value < (1024 * 1024 * 10)) {
            // 10MBまではKB表示
            return sprintf('%s[kb]', round($value / 1024, 1));
        } else {
            return sprintf('%s[mb]', round($value / (1024 * 1024), 2));
        }
    }

    /**
     * @param int $threshold 閾値(MB)
     * @return bool
     */
    protected function isOverUsingMemory($threshold)
    {
        return round(memory_get_peak_usage(1) / 1024 / 1024) > $threshold;
    }

    /**
     * 処理時間を取得
     *
     * @return string
     */
    protected function getProcessingTime()
    {
        return $this->formatTime(microtime(true) - APP_START_TIME);
    }

    /**
     * メモリ使用量のピーク値を取得
     *
     * @return float
     */
    protected function getPeekMemory()
    {
        return $this->formatMemory(memory_get_peak_usage(true));
    }

}

Kernelクラスに登録

app\Http\Kernel.php

/**
 * 親クラスからコピー
 */
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,

    // この一行を追加
    \App\Bootstrap\ApplicationLog::class,
];
app\Console\Kernel.php

/**
 * 親クラスからコピー
 */
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,

    // この一行を追加
    \App\Bootstrap\ApplicationLog::class,
];

以上です。

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6