[PHP]Monolog와 함께 로그를 시작하자 - 1

PHP에서는 주로 JS에서 console.log | console.debug 와 유사하게 var_dump | print_r | echo | sys_log | error_log 등 다양한 방식으로 로그를 남기고 있습니다.

PSR-3을 준수하고 있는 로깅 프레임워크로, 거의 대부분의 로깅 플랫폼과 연결할 수 있는 핸들러(Slack, ElasticSearch, Mail, NewRelic 등)를 제공하고 있습니다.

RFC 5424(Syslog Protocol이라고 하는데 더 공부해봐야할 것 같습니다.)에 정의된 로그 레벨을 모두 지원하고 있습니다.

  • DEBUG(100)
  • INFO(200)
  • NOTICE(250)
  • WARNING(300)
  • ERROR(400)
  • CRITICAL(500)
  • ALERT(550)
  • EMERGENCY(600)

간단하게 Logger Instance에 Record를 추가하면, 해당 인스턴스에 추가 해두었던 핸들러에 이벤트를 전파하는 것으로 보입니다.(한개의 로그를 여러곳에 저장할 수 있는 이점을 가지고 있습니다.)

PHP Composer로 관리할 수 있는 라이브러리이므로 Composer를 이용하여 설치합니다.

composer require monolog/monolog

우선적으로 use를 사용하여 사용할 Namespace를 추가합니다.

<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;

Logging Channel의 이름을 설정하여 객체를 생성합니다.

// Create the logger
$logger = new Logger('Application');

로그를 전파할 핸들러를 추가합니다.

  • php:stderr 또는 원격이나 로컬 파일 기타에 사용할 Stream Handler를 설정합니다.
  • Slack Webhook Url으로 보내기 위해 Slack WebHook Handler를 설정합니다.
// Now add some handlers
$logger->pushHandler(new StreamHandler(__DIR__ . '/app.log', Logger::DEBUG));
$logger->pushHandler(new SlackWebhookHandler({{WEBHOOK_URL}}, {{CHANNEL}}, {{USERNAME}}, false, null, false, false, Logger::INFO));

아래와 같은 함수를 호출하여 로그를 쌓을 수 있습니다.

// You can now use your logger
$logger->info('Welcome To Monolog');

/*********
 * app.log
 *********/
// [2019-05-10 17:03:10] Application.INFO: Welcome To Monolog [] []

Legacy한 프로젝트에서는 주로 컨테이너 객체라는 개념이 없는 경우가 많은데, 프로젝트 내부에서도 글로벌 변수에 담아서 Logger 객체를 사용해야하나 고민하였습니다. 문서를 확인하다보니 이를 위한 Monolog\Registry라는 유틸 클래스가 있었고, 이와 같이 사용할 수 있습니다.

/****************
 * bootstrap.php
 ****************/
 
<?php
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Registry;

$logger = new Logger('Application');
$logger->pushHandler(new StreamHandler(__DIR__ . '/app.log', Logger::DEBUG));
Registry::addLogger($logger,'ApplicationLog');

/****************
 * foo.php
 ****************/
<?php
use Monolog\Registry;

require_once __DIR__ . "/bootstrap.php";

function logInfo($message) {
    $logger = Registry::getInstance('ApplicationLog');
    $logger->info($message);
}

logInfo('I am Global Logging');

/*********
 * app.log
 *********/
// [2019-05-10 17:03:10] Application.INFO: I am Global Logging [] []

이와 같이 bootstrap.php 파일에서 Register에 등록한 Logger 객체는 global 변수를 사용하지 않아도 클래스 / 함수 상관 없이 어디에서든지 사용 가능해집니다.

더 좋은 활용 방법이 있으시다면 공유 부탁드리겠습니다.

자세한 사항은 Monolog-Usage에서 확인 하실 수 있습니다.