Laravel 로깅: 알아야 할 모든 것
게시 됨: 2022-08-19최신 애플리케이션을 개발할 때 로깅은 우선 순위 목록의 맨 위에 있어야 합니다.
로깅은 개발 및 프로덕션 모두에서 앱을 시각화하는 방법을 제공하여 투명성과 가시성을 가능하게 합니다. 적절하게 구조화된 로깅을 사용하면 앱에서 장애 지점과 성능 병목 현상을 사전에 식별할 수 있으므로 최신 애플리케이션을 유지 관리하기가 더 쉬워질 수 있습니다.
라라벨 프레임워크는 적절한 구조의 로깅 시스템을 즉시 구성하는 데 관련된 모든 장애물을 처리하는 강력한 로깅 시스템과 함께 제공됩니다. Laravel 6.5에 도입된 이 새로운 로깅 시스템은 강력하며 이 기사에서 살펴보겠습니다.
이 기사에서는 Laravel 로깅의 기본 사항과 다음 프로젝트에서 Laravel 로깅을 사용해야 하는 이유를 살펴봅니다. 구조화된 로깅과 중앙 집중식 로깅에 대해 자세히 설명합니다. 또한 Todo 애플리케이션을 빌드하여 Laravel 로깅을 구현하는 방법을 배우게 됩니다.
이미 다음과 같은 사항이 있는 경우 이 기사에서 더 많은 것을 얻을 수 있습니다.
- 웹 개발에 대한 좋은 지식
- 라라벨에 대한 기본 이해
- Laravel로 앱 빌드
Laravel 로깅이란 무엇입니까?
Laravel 로깅은 Monolog라는 바이러스성 PHP 로깅 시스템을 사용하여 Laravel이 로깅 또는 자동 문제 보고를 처리하는 방법에 관한 것입니다. 그러나 인기 있는 기존 라이브러리를 사용하여 다른 프레임워크 기능을 구현한다는 Laravel의 철학으로 인해 Laravel은 모든 로깅 요구 사항에 대해 Monolog를 사용합니다.
Monolog는 파일, 소켓, 데이터베이스 및 기타 웹 서비스에 로그를 보내도록 구성할 수 있는 매우 유연하고 널리 사용되는 PHP 로깅 라이브러리입니다. Monolog는 표준 텍스트 파일에서 고급 타사 로그 관리 서비스로 로그를 작성하기 위한 친숙한 인터페이스를 제공합니다. Laravel은 일반적으로 표준 로깅 구성 파일을 사용하도록 Monolog를 설정합니다.
Monolog 및 그 기능에 대한 자세한 내용은 이 문서의 범위를 벗어나는 공식 문서를 확인하십시오.
Monolog를 사용하여 Laravel 로깅을 구성하고 구현하기 전에 Laravel 로깅과 다양한 유형을 사용해야 하는 더 많은 이유를 살펴보겠습니다.
왜 Laravel 로깅을 사용합니까?
로깅이 필요한 이유는 무엇입니까?
Twelve-Factor App 선언문은 로깅이 성능 및 모니터링의 핵심이기 때문에 로깅을 최신 애플리케이션의 중요한 관심사 중 하나로 취급합니다.
로그는 프로덕션에서 발생하는 오류와 오류가 발생한 위치를 자세히 이해하는 데 도움이 됩니다. 또한 적절한 로그 구조를 통해 특정 사용자, 오류를 일으킨 조치, 더 빠른 버그 수정 및 유지 관리를 위한 가능한 솔루션을 표시할 수 있습니다.
구조적 로깅은 프로덕션에서 결함을 해결하고 문제를 해결하는 데 도움을 주어 프로덕션 애플리케이션의 생명을 구합니다. 또한 실시간 분석 및 보고를 위한 특수 로깅 도구를 사용하여 모든 로그 메시지를 실시간으로 모니터링하고 수집할 수 있습니다.
이러한 이유로 구조화된 로깅을 다음 최신 애플리케이션 프로젝트에서 최우선 순위로 지정해야 합니다.
사용 가능한 다양한 로깅 스타일의 개요를 살펴보겠습니다.
라라벨 로깅의 기초
로깅의 기본을 배우면 Laravel이 로깅을 처리하는 방법과 구조화된 로깅 관행을 개선할 수 있는 방법을 이해하는 데 도움이 됩니다.
로깅 절차를 구현하는 방법을 더 잘 이해하기 위해 로깅의 두 가지 필수 개념을 살펴보겠습니다.
Laravel 구조적 로깅
소프트웨어 개발에서 구조화된 로깅은 애플리케이션 로그에 대해 미리 결정되고 일관된 메시지 형식을 구현합니다. 이 형식을 사용하면 메시지를 일반 텍스트 형식보다 훨씬 더 잘 모니터링, 조작 및 시각화할 수 있는 데이터로 처리할 수 있습니다.
프로덕션 환경에서 애플리케이션에 문제가 발생할 때 로그 파일은 개발자에게 필수적인 자산이기 때문에 최신 애플리케이션 개발에서 구조화된 로깅 접근 방식을 구현해야 합니다.
Laravel은 Monolog를 사용하므로 개발자는 특정 유형의 정보를 수신하도록 로거를 구성하고, 로그 파일을 다양한 형식으로 저장하고, 시각화를 위해 다양한 타사 로그 관리 서비스에 로그를 전송하여 구조화된 로깅을 빠르게 구현할 수 있습니다.
Laravel 중앙 집중식 로깅
중앙 집중식 로깅 시스템은 간편한 통합 및 시각화를 위해 여러 소스에서 중앙 집중식 로그 관리(CLM) 솔루션으로 로그를 보내는 곳입니다. 그러나 CLM은 다양한 소스에서 로그 메시지를 수집하고 데이터를 통합하여 쉽게 처리하고 시각화하는 전문 로거 솔루션입니다.
데이터 수집 외에도 CLM은 로그 데이터 분석 및 분석 후 데이터의 명확한 표시를 지원할 것으로 예상됩니다.
구조적 로깅 대 기본 로깅
구조적 로깅과 기본(비구조적) 로깅의 차이점과 라라벨 프로젝트에서 구조적 로깅을 사용해야 하는 이유를 살펴보겠습니다.
기본 로깅
기본 로깅에서 로그 파일은 개별 로그를 쿼리하고 식별하기 위해 제한된 데이터와 함께 원시 형식으로 저장됩니다.
기본 로깅을 사용할 때 개발자는 사용자 지정 도구를 개발하거나 로그 형식을 지원하는 제한된 도구를 사용하지 않는 한 타사 분석 도구를 사용하여 로그를 읽고 보고 분석할 수 없습니다.
기본 로깅을 사용하지 않는 세 가지 큰 이유가 있습니다.
- 중앙 집중식 로그 관리 시스템은 추가 지원 없이는 데이터를 사용할 수 없습니다.
- 기본 로깅 솔루션의 데이터를 읽고 파싱하기 위해서는 맞춤형 솔루션이 필요합니다.
- 기본 로깅 데이터는 구조화되지 않은 원시 데이터이므로 관리자가 읽기가 어려울 수 있습니다.
구조화된 로깅
구조적 로깅은 표준 로그 구조를 지원하는 오픈 소스 타사 로그 분석 도구를 사용하여 로그를 읽고, 보고, 분석함으로써 개발자의 시간을 절약합니다.
로그는 구조화된 로깅이 달성하고자 하는 아래 나열된 올바른 데이터를 포함하는 경우 유용합니다. 구조화된 로깅에 포함된 데이터를 사용하여 대시보드, 그래프, 차트 및 기타 유용한 시각화를 생성하여 애플리케이션의 상태를 확인할 수 있습니다.
다음은 구조화된 로그 메시지에 포함할 수 있는 정보의 기본 예입니다. 또한 필요에 맞게 데이터를 완전히 사용자 지정할 수 있습니다.
다음은 구조화된 로깅으로 수집할 수 있는 데이터의 몇 가지 예입니다.
- 기능을 실행하는 데 사용되는 포트
- 이벤트가 발생한 날짜 및 시간
- 고객 사용자 이름 또는 ID
- 이벤트 설명(로그 메시지)
- 기능을 실행하는 데 사용되는 프로토콜
- 트리거된 이벤트의 위치(API 또는 실행 중인 앱 표시)
- 고유 이벤트 ID
- 트리거된 작업 유형(로그 수준)
로그에는 솔루션이나 로그 이벤트의 원인을 쉽게 시각화할 수 있는 충분한 데이터가 포함되어야 합니다. 또한 비밀번호나 민감한 데이터와 같은 모든 유형의 정보를 로그에 저장해서는 안 됩니다.
이제 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에서 데이터베이스를 시드하는 방법을 학습하여 페이커 데이터로 할 일을 시드할 수 있습니다.
모노로그 개요
Laravel Monolog를 사용하면 구조화된 로그를 이메일, Slack, 파일, 소켓, 받은 편지함, 데이터베이스 및 다양한 웹 서비스와 같은 다양한 채널로 스트리밍하고 보낼 수 있습니다. Laravel에서는 config/logging.php 에 있는 단일 구성 파일에서 로깅을 구성할 수 있습니다.
구성 파일은 선택할 수 있는 미리 정의된 로그 드라이버와 함께 제공되며 기본 드라이버는 single
채널을 사용하여 storage/logs 폴더에 있는 laravel.log 파일에 기록하는 stack
입니다. 몇 가지 Laravel 로그 드라이버를 사용하여 구조화된 로깅을 시연할 것입니다.
Laravel은 일반적으로 TodosController.php 컨트롤러 파일에 간략히 설명되어 있듯이 Logs와 상호 작용할 수 있는 몇 가지 방법을 제공합니다.
컨트롤러에서 로그 메시지 쓰기
새로 생성된 TodosController.php 컨트롤러 파일에서 app/Http/Controllers 폴더를 열고 다음 코드를 붙여넣습니다.
<?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
키를 사용하여 사용자 정의 MonologFormatterHtmlFormatter
를 daily
드라이버에 추가합니다.
다른 채널에 로그 보내기
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 선언문에서 현대 응용 프로그램의 가장 중요한 문제 중 하나로 제안한 이유입니다.
효과적인 로깅을 통해 프로덕션 준비 애플리케이션에서 발생하는 오류와 결함을 쉽게 읽고, 보고, 시각화할 수 있습니다. 이를 위해서는 프로젝트 시작부터 바로 애플리케이션에 구조화된 로그인을 구현하는 것이 중요합니다.
이 기사에서는 Laravel 로깅과 다음 프로젝트에서 Laravel 로깅을 사용해야 하는 이유를 살펴보았습니다. 구조적 로깅과 중앙 집중식 로깅 모두에 대해 자세히 논의했습니다. 또한 Todo 애플리케이션을 빌드하여 Laravel 로깅을 구현하는 방법을 배웠습니다.
다음 앱에 로그인을 어떻게 구현할 계획인가요? 의견 섹션에서 알려주십시오.