Laravel ロギング: 知っておくべきことすべて

公開: 2022-08-19

最新のアプリケーションを開発するときは、ロギングを優先リストの一番上に置く必要があります。

ロギングは、開発と本番の両方でアプリを視覚化する方法を提供し、透明性と可視性を実現します。 適切に構造化されたログを使用すると、アプリの障害点やパフォーマンスのボトルネックを事前に特定できるため、最新のアプリケーションの保守が容易になります。

Laravel フレームワークには、適切に構造化されたログ システムをすぐに構成するために必要なすべてのハードルを処理する堅牢なログ システムが付属しています。 Laravel 6.5 で導入されたこの新しいロギング システムは強力であり、この記事で詳しく説明します。

この記事では、Laravel ロギングの基本と、次のプロジェクトで Laravel ロギングを使用する理由について説明します。 構造化ログと集中ログについて詳しく説明します。 さらに、Todo アプリケーションを作成して Laravel ロギングを実装する方法を学びます。

次のことをすでに知っている場合は、この記事をさらに活用できます。

  • Web開発の十分な知識
  • Laravelの基本的な理解
  • Laravel でアプリを構築する

Laravelロギングとは?

Laravel ロギングは、Monolog と呼ばれるバイラル PHP ロギング システムを使用して、Laravel がロギングまたは自動問題レポートを処理する方法に関するものです。 ただし、一般的な既存のライブラリを使用してさまざまなフレームワーク機能を実装するという Laravel の哲学により、Laravel はすべてのロギング ニーズに Monolog を採用しています。

Monolog は、ログをファイル、ソケット、データベース、およびその他の Web サービスに送信するように構成できる、非常に柔軟で人気のある PHP ロギング ライブラリです。 Monolog は、標準のテキスト ファイルから高度なサードパーティのログ管理サービスにログを書き込むための使い慣れたインターフェイスを提供します。 通常、Laravel は標準のロギング構成ファイルを使用するように Monolog をセットアップします。

Monolog とその機能の詳細については、この記事の範囲を超えているため、公式ドキュメントを確認してください。

Monolog を使用した Laravel ロギングの構成と実装に入る前に、Laravel ロギングとさまざまなタイプを使用するその他の理由を調べてみましょう。

Laravel ロギングを使用する理由

なぜロギングが必要なのですか?

Twelve-Factor App マニフェストは、ロギングがパフォーマンスと監視の鍵であるため、ロギングを最新のアプリケーションの重要な懸念事項の 1 つとして扱っています。

ログは、本番環境で発生したエラーとその発生場所を詳細に理解するのに役立ちます。 さらに、適切なログ構造を使用すると、特定のユーザー、エラーの原因となったアクション、およびバグ修正とメンテナンスを迅速に行うための可能な解決策を示すことができます。

構造化ログは、本番環境での欠陥のトラブルシューティングと問題の解決に役立つため、本番アプリケーションの命の恩人です。 さらに、ライブ分析とレポート用の専用ログ ツールを使用して、すべてのログ メッセージをリアルタイムで監視および収集できます。

これらの理由から、次の最新のアプリケーション プロジェクトでは、構造化ログを最優先事項にする必要があります。

利用可能なさまざまなロギング スタイルの概要を見てみましょう。

Laravel ロギングの基本

ロギングの基本を学ぶことは、Laravel がロギングを処理する方法と、構造化されたロギング プラクティスを改善する方法を理解するのに役立ちます。

ロギング手順を実装する方法をよりよく理解するために、ロギングの 2 つの重要な概念を調べてみましょう。

Laravel 構造化ロギング

ソフトウェア開発では、構造化ログは、アプリケーション ログ用に事前定義された一貫したメッセージ形式を実装しています。 この形式を使用すると、メッセージをデータとして扱うことができ、通常のテキスト形式よりもはるかに優れた監視、操作、および視覚化が可能になります。

本番環境でアプリケーションに問題が発生した場合、ログ ファイルは開発者にとって不可欠な資産であるため、最新のアプリケーション開発では構造化されたログ アプローチを実装する必要があります。

Laravel は Monolog を使用しているため、開発者はロガーを構成して特定の種類の情報を受信し、ログ ファイルをさまざまな形式で保存し、視覚化のためにさまざまなサードパーティのログ管理サービスにログを送信することで、構造化されたログをすばやく実装できます。

Laravel集中ロギング

集中ログ システムでは、ログが複数のソースから集中ログ管理 (CLM) ソリューションに送信され、統合と視覚化が容易になります。 ただし、CLM は、さまざまなソースからログ メッセージを収集し、データを統合して処理と視覚化を容易にする特殊なロガー ソリューションです。

データ収集のほかに、CLM はログ データの分析と分析後のデータの明確な表示をサポートすることも期待されています。

構造化ログと基本ログ

構造化ロギングと基本的な (非構造化) ロギングの違いと、Laravel プロジェクトで構造化ロギングを使用する理由を調べてみましょう。

基本ロギング

基本ログでは、ログ ファイルは生の形式で保存され、個々のログを照会して識別するための限られたデータが含まれます。

基本ログを使用する場合、開発者は、カスタム ツールを開発するか、ログ形式をサポートする限定的なツールを使用しない限り、ログの読み取り、表示、および分析にサードパーティの分析ツールを使用できません。

基本ログの使用を避けるべき大きな理由は 3 つあります。

  1. 集中ログ管理システムは、追加のサポートなしではデータを処理できません。
  2. 基本的なロギング ソリューションのデータを読み取って解析するには、カスタマイズされたソリューションが必要です。
  3. 基本的なログ データは未加工で構造化されていないため、管理者が読み取るのは難しい場合があります。

構造化ログ

構造化ログは、標準ログ構造をサポートするオープンソースのサードパーティ ログ分析ツールを使用してログを読み取り、表示、分析することで、開発者の時間を節約します。

ログは、以下に示す正しいデータが含まれている場合に役立ちます。これは、構造化ログの目的です。 構造化ログに含まれるデータを使用して、ダッシュボード、グラフ、チャート、その他の役立つ視覚化を作成し、アプリケーションの正常性を判断できます。

これらは、構造化されたログ メッセージに含めることができる情報の基本的な例です。 さらに、ニーズに合わせてデータを完全にカスタマイズできます。

構造化ログで収集できるデータの例を次に示します。

  1. 関数の実行に使用されるポート
  2. イベントが発生した日時
  3. 顧客のユーザー名または ID
  4. イベントの説明 (ログ メッセージ)
  5. 関数の実行に使用されるプロトコル
  6. トリガーされたイベントの場所 (API または実行中のアプリを示す)
  7. 一意のイベント ID
  8. トリガーされたアクションのタイプ (ログ レベル)

ログには、解決策やログ イベントの理由を簡単に視覚化できる十分なデータが含まれている必要があります。 また、パスワードや機密データなど、すべての種類の情報をログに保存しないでください。

Laravel ロギングが何であるかを垣間見たので、ファーストクラスの市民としてロギングを使用してアプリケーションを構築することにより、Laravel ロギングの実装に移りましょう。

Todo アプリで Laravel ロギングを実装する方法

新しい Laravel プロジェクトを作成し、Laravel ロギングを実装することで、これまでに学んだことを適用します。

これまでに Laravel を使用したことがない場合は、Laravel とは何かを読んだり、優れた Laravel チュートリアルのリストを参照して開始したりできます。

ララベルのセットアップ

まず、以下のコマンドを使用して新しい Laravel インスタンスを作成します。 詳細については、公式ドキュメントを参照してください。

以下のコマンドを実行する前に、コンソールを開き、PHP プロジェクトを保存する場所に移動します。 Composer が正しくインストールされ、構成されていることを確認してください。

 composer create-project laravel/laravel laravel-logging-app cd laravel-logging-app // Change directory to current Laravel installation php artisan serve // Start Laravel development server

データベースの構成とシード

次に、データベースをセットアップし、新しいTodoモデルを作成し、テスト用に 200 個の偽データをシードします。

データベース クライアントを開き、新しいデータベースを作成します。 名前laravel_logging_app_dbで同じことを行い、 .envファイルにデータベース資格情報を入力します。

 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_logging_app_db DB_USERNAME=//DB USERNAME HERE DB_PASSWORD=//DB PASSWORD HERE

次に、次のコマンドを実行して、移行とTodoモデルを同時に作成します。

 php artisan make:model Todo -mc

新しく作成された移行が見つかったdatabase/migrations/xxx-create-todos-xxx.phpを開き、次のコードを貼り付けます。

 <?php use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreateTodosTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('todos', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('description')->nullable(); $table->boolean('is_completed')->default(false); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('todos'); } }

Faker を使用して Laravel にデータベースをシードする方法を学習することで、todo にフェイカー データをシードすることができます。

ダウンタイムや WordPress の問題に悩まされていませんか? Kinstaは、時間を節約するために設計されたホスティングソリューションです! 私たちの機能をチェックしてください

モノログの概要

Laravel Monolog を使用すると、メール、Slack、ファイル、ソケット、受信トレイ、データベース、さまざまな Web サービスなどのさまざまなチャネルに構造化ログをストリーミングして送信できます。 Laravel では、 config/logging.phpにある単一の構成ファイルからロギングを構成できます。

構成ファイルには、選択可能な事前定義されたログドライバーが付属しており、デフォルトのドライバーは、 singleのチャネルを使用してstorage/logsフォルダーにあるlaravel.logファイルにログを記録するstackです。 いくつかの Laravel ログ ドライバーを使用して、構造化ログのデモを行います。

TodosController.phpコントローラー ファイルで一般的に示されているように、Laravel はログと対話するためのいくつかのメソッドを提供します。

コントローラでのログ メッセージの書き込み

app/Http/Controllersフォルダーにある新しく作成されたTodosController.phpコントローラー ファイルを開き、次のコードを貼り付けます。

 <?php namespace AppHttpControllers; use AppModelsTodo; use IlluminateHttpRequest; use AppHttpControllersController; use IlluminateSupportFacadesAuth; use IlluminateSupportFacadesLog; class TodosController extends Controller { public function index(Request $request) { $todos = Todo::all(); Log::warning('User is accessing all the Todos', ['user' => Auth::user()->id]); return view('dashboard')->with(['todos' => $todos]); } public function byUserId(Request $request) { $todos = Todo::where('user_id', Auth::user()->id)->get(); Log::info('User is accessing all his todos', ['user' => Auth::user()->id]); return view('dashboard')->with(['todos' => $todos]); } public function show(Request $request, $id) { $todo = Todo::find($id); Log::info('User is accessing a single todo', ['user' => Auth::user()->id, 'todo' => $todo->id]); return view('show')->with(['todo' => $todo]); } public function update(Request $request, $id) { # Validations before updating $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first(); Log::warning('Todo found for updating by user', ['user' => Auth::user()->id, 'todo' => $todo]); if ($todo) { $todo->title = $request->title; $todo->desc = $request->desc; $todo->status = $request->status == 'on' ? 1 : 0; if ($todo->save()) { Log::info('Todo updated by user successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]); return view('show', ['todo' => $todo]); } Log::warning('Todo could not be updated caused by invalid todo data', ['user' => Auth::user()->id, 'todo' => $todo->id, 'data' => $request->except('password')]); return; // 422 } Log::error('Todo not found by user', ['user' => Auth::user()->id, 'todo' => $id]); return; // 401 } public function store(Request $request) { Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]); # Validations before updating $todo = new Todo; $todo->title = $request->title; $todo->desc = $request->desc; $todo->user_id = Auth::user()->id; if ($todo->save()) { Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]); return view('show', ['todo' => $todo]); } Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]); return; // 422 } public function delete(Request $request, $id) { Log::warning('User is trying to delete a single todo', ['user' => Auth::user()->id, 'todo' => $id]); $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first(); if ($todo) { Log::info('User deleted a single todo successfully', ['user' => Auth::user()->id, 'todo' => $id]); $todo->delete(); return view('index'); } Log::error('Todo not found by user for deleting', ['user' => Auth::user()->id, 'todo' => $id]); return; // 404 } }

TodoControllerの各メソッド内に、特定のログ レベルを持つLogファサードを追加して、送信するエラーのタイプを定義しました。 以下は、

storeメソッドでファサードをログに記録します。

 public function store(Request $request) { Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]); # Validations before updating $todo = new Todo; $todo->title = $request->title; $todo->desc = $request->desc; $todo->user_id = Auth::user()->id; if ($todo->save()) { Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]); return view('show', ['todo' => $todo]); } Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]); return; // 422 }

ログ メッセージのフォーマット

Laravel が使用するデフォルトのLineFormatterに慣れていないとします。これは、読みやすく役立つメッセージを提供する優れた機能を果たします。

その場合、ユース ケースに合わせてカスタマイズされたフォーマッタ オブジェクトを簡単にスピンアップし、アプリケーション全体で使用できます。

Monolog の公式ドキュメントには、使用可能なフォーマッタの完全なリストが記載されており、カスタム フォーマッタを簡単に作成できます。

Laravel では、 config/logging.phpにある構成ファイル内の以下のようなリストにカスタム フォーマッタを追加することで、カスタム フォーマッタを使用するように任意のドライバを簡単に設定できます。

 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 14, 'formatter' => MonologFormatterHtmlFormatter::class, 'formatter_with' => [ 'dateFormat' => 'Ym-d', ] ],

上記の例では、 dailyチャネル構成でformatterおよびformatter_withキーを使用してカスタムMonologFormatterHtmlFormatterdailyドライバに追加し、日付の形式を変更しています。

異なるチャネルへのログの送信

Monolog の助けを借りて、Laravel は異なるチャネルや複数のチャネルに同時にログを送信できます。

これらの簡単な手順に従って、Slack チャネルにログを送信する方法を示しましょう。 デフォルトのログ チャネルを Slack に変更し、 .envファイルに Slack Webhook URL を追加します。

 LOG_CHANNEL=slack LOG_SLACK_WEBBHOOK_URL= Slack_webhook_url_here

次に、以下に示すようなLogファサードを使用してアプリケーションにメッセージを記録することにより、構成をテストします。

 Log::debug("The API instance is on fire caused by:", ['user' => 1])

Slack チャネルを開いて、Webhook URL の生成時に指定した目的のチャネルに出力されたエラーを確認できます。

概要

ロギングは、アプリケーションの他の要素と同じくらい、またはそれ以上に重要です。 これが、Twelve-Factor App マニフェストで、最新のアプリケーションの最も重要な懸念事項の 1 つとして提案されている理由です。

効果的なログを使用すると、本番対応のアプリケーションで発生したエラーや欠陥を簡単に読み取り、表示し、視覚化できます。 そのためには、プロジェクトの最初から構造化されたログをアプリケーションに実装することが重要です。

この記事では、Laravel ロギングと、次のプロジェクトでそれを使用する理由について説明しました。 構造化ログと集中ログの両方について詳しく説明しました。 さらに、Todo アプリケーションを作成して Laravel ロギングを実装する方法を学びました。

次のアプリにログインをどのように実装する予定ですか? コメント欄でお知らせください。