Programming/PHP

[Codeigniter 3.x] 쿼리 로그 남기기 #2

minarae7 2023. 1. 29. 18:32
728x90
반응형

앞에서 남긴 로그를 보면 포멧팅 되지 않은 상태로 출력된다. 이렇게 출력된 로그는 짧은 쿼리는 상관없겠지만 복잡한 쿼리를 확인하기에는 다소 무리가 있다.

비교적 간단한 쿼리이지만 쿼리를 작성할 때 로그를 출력할 것을 생각하고 작성하지 않는다면 복잡한 쿼리는 보기 어려울 것이다. 위의 이미지의 쿼리는 쿼리를 실제로 작성한 쿼리이기 때문에 그나마 들여쓰기라도 했지만 ORM을 통해서 생성되는 쿼리는 더 복잡하게 출력된다.
그래서 쿼리 로그를 남길 때 일정 부분 포멧팅해줄 필요가 있다. 물론 필요한 부분의 쿼리를 복사해서 인터넷에서 포멧팅해주는 사이트에서 해줄 수 있을 것이다. 하지만 쿼리를 한 번에 알아보고 싶다는 필요가 있다. 포멧팅을 하면 로그의 용량은 증가할 것이지만 용량을 포기하고 로그를 한 번에 보고 싶다는 필요가 있다.
그래서 검색하다가 찾은 라이브러리가 Sql_formatter라는 라이브러리이다.

 

GitHub - jdorn/sql-formatter: A lightweight php class for formatting sql statements. Handles automatic indentation and syntax hi

A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting. - GitHub - jdorn/sql-formatter: A lightweight php class for formatting sql statements. ...

github.com

위의 레포지토리에서 확인하면 다양한 기능을 활용할 수 있다. 여기서는 단순하게 들여쓰기 정도 해주는 용도로 활용할 것이다. 더 많은 것이 하고 싶다면 HTML로 태그를 달아주는 기능도 있다.
우선 위의 레포지토리에서 /lib/SqlFormatter.php를 다운받아서 /application/libraries 안에 위치하도록 한다.
그리고 파일의 이름을 SqlFormatter.php에서 Sql_formatter.php로 변경하고 파일 안에 Class 이름도 Sql_formatter로 변경한다. 이렇게 변경하는 이유는 CI 3.x 버전에서 Camel Case로 파일 이름을 읽어 오지 못한다. 이 파일을 읽어오도록 하려면 또 많은 수정을 해야 하기 때문에 그냥 파일 이름과 클래스 이름을 CI에서 읽을 수 있는 형태로 변경한다.
앞에서 작성했던 코드에서 다음 코드를 추가한다.

function log_queries()
{
    //....이전 코드 생략
    $ci->load->library('Sql_formatter');  // 추가한 라이브러리를 읽어옴
    $ci->sql_formatter::$tab = '    ';    // 들여쓰기 형태를 지정(Space 4)
    //....중간 코드 생략
    if (count($queries) > 0) {
        foreach ($queries as $key => $query) {
            $output .= "[times:{$time[$key]}]\n";
            $output .= $ci->sql_formatter::format($query, false) . "\n";
            $output .= "========================================================================\n";
        }
    }
    //....이후 코드 생략
}

앞에 코드에서 $ci에 변수에 CI의 instance를 담았으니 Contoller에서 $this로 사용하는 것과 같이 사용할 수 있다.
$ci->load->library를 통해서 앞에서 복사해둔 라이브러리를 읽어들인다. 그 아래에서 Tab을 어떻게 처리할지 지정한다. 위의 코드에서는 Space 4칸으로 지정하였다.
그리고 로그 메시지를 생성할 때 format 함수를 통해서 개발자가 읽기 편하도록 포멧팅하도록 하였다.
생각보다 간단한 코드인데 꽤 유용한 코드라고 할 수 있을 것이다.
여기서 완성된 코드는 다음과 같다.

<?php
class LogQueryHook
{
    function log_queries()
    {
        $ci =& get_instance();
        $ci->load->library('Sql_formatter');
        $ci->sql_formatter::$tab = '    ';
        
        $time = $ci->db->query_times;
        $output = '';
        $queries = $ci->db->queries;

        if (count($queries) > 0) {
            foreach ($queries as $key => $query) {
                $output .= "[times:{$time[$key]}]\n";
                $output .= $ci->sql_formatter::format($query, false) . "\n";
                $output .= "========================================================================\n";
            }
        }

        if (empty($output) === true) {
            return;
        }

        $ci->load->helper('file');

        $config_log_path = APPPATH . "logs/";
        $date = date("Ym");

        $dir = $config_log_path . 'QueryLog' . $date;

        if (file_exists($dir) === false) {
            @mkdir($dir);
            chmod($dir, 0755);
        }
        $ip = $ci->input->ip_address();

        $filepath = $dir . '/Query-log-' . date('Ymd') . '.php';

        $msg = "[" . date("Y-m-d H:i:s") . "][" . $ci->router->class . "/" . $ci->router->method . "]\n";
        $msg .= $output . "\n\n";
        $msg .= "IP_ADDRESS:" . $ip . "\n";
        $msg .= "==========================\n\n";

        $handle = fopen($filepath, "a+");
        flock($handle, LOCK_EX);
        fwrite($handle, $msg);
        flock($handle, LOCK_UN);
        fclose($handle);
    }
}

코드를 이와 같이 수정하고 나면 위의 이미지처럼 출력된 쿼리는 아래와 같이 변경된다.

728x90
반응형