Логирование процессов

Быстрый старт

Данное решение служит для удобного логирования в БД. В простом случае не требуется никакой настройки. Необходимо только чтоб в БД были две таблички, которые можно создать так:

                    $gp = GP::instance();
                    $gp->createTablesForLog();
                

Если необходимо записать в лог информационное сообщение что по проекту project №001 был создан бэкап, то пишем:

                    $log = $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
                

А теперь нам необходимо дополнить запись лога дополнительными свойствами. К примеру мы хотим записать размер бэкапа и email заинтересованных лиц.

                    $log->prop('sizeBackup', '10249')
                        ->prop('email', 'admin@mail.ru')
                        ->prop('email', 'support@mail.ru')
                        ->prop('email', 'vasya@mail.ru');
                

Если же случай более сложный и дополнительное свойство конкретного лога необходимо записать в другом месте приложения, в другом классе. Мы сначала сохраним нашу переменную и затем сможем обращаться к ней из любого места.

                    $log->save('backup');
                

Теперь в другом классе приложения мы хотим записать дополнительную информацию по сервер. Записать ip сервера и последующие свойства хотим сделать дочерними по отношению к этому.

                    $gp = GP::instance();
                    $gp->log('backup')
                       ->prop('server', '192.168.0.99')
                       ->prop('server/freePlace', '23944556')
                       ->prop('server/percentFreePlace', '20%')
                       ->prop('server/path', '/home/a1/backup/003.sql')
                

Основная информация по логам хранится в таблице log (дефолтное название), берем оттуда нужные данные. Если необходимо получить дополнительные свойства в древовидной структуре, то достаточно вызвать функцию getLog($id) или getCanonLog($id) и передать туда id (или массив id) из таблицы log.

                    $data = $gp->getCanonLog([1, 2, 3]);
                    /*  Содержимое массива $data:
                     *  [
                     *      [
                     *          'id' => 1,
                     *          'type' => 'info',
                     *          'mode' => 'project №001',
                     *          'message' => 'create backup',
                     *          'ip' => '172.18.0.2',
                     *          'file_name' => '',
                     *          'number_line' => '',
                     *          'date_create' => '2021-09-28 13:36:08',
                     *          'properties' => [
                     *              'sizeBackup' => [
                     *                  'val' => [10249],
                     *                  'child' => []
                     *              ],
                     *              'server' => [
                     *                  'val' => ['192.168.0.99'],
                     *                  'child' => [
                     *                      'freePlace' => [
                     *                          'val' => [23944556],
                     *                          'child' => []
                     *                      ],
                     *                      'percentFreePlace' => [
                     *                          'val' => ['20%'],
                     *                          'child' => []
                     *                      ]
                     *                  ]
                     *              ],
                     *              'email' => [
                     *                  'val' => ['admin@mail.ru', 'support@mail.ru', 'vasya@mail.ru'],
                     *                  'child' => []
                     *              ]
                     *          ]
                     *      ],
                     *      .....
                     *  ]
                     */
                

База данных

В БД должно быть две таблицы, куда будут записываться логи, это: log и val_log. Можно создать эти таблицы с помощью функции $gp->createTablesForLog().

Или же вы можете создать таблицы сами, но количество колонок и их тип должен быть таким же.

                                        CREATE TABLE `log` (
                                          `id` INT NOT NULL AUTO_INCREMENT,
                                          `type` VARCHAR(10) NOT NULL,
                                          `title` VARCHAR(255) NOT NULL,
                                          `message` VARCHAR(4000) NULL,
                                          `ip` VARCHAR(64) NULL,
                                          `file_name` VARCHAR(255) NULL,
                                          `number_line` INT NULL,
                                          `date_create` DATETIME NOT NULL DEFAULT now(),
                                        PRIMARY KEY (`id`))
                                        ENGINE = InnoDB;

                                        CREATE TABLE `val_log` (
                                          `id` INT NOT NULL AUTO_INCREMENT,
                                          `log_id` INT NOT NULL,
                                          `parent_id` INT NULL,
                                          `property` VARCHAR(255) NOT NULL,
                                          `val` TEXT(65000) NOT NULL,
                                          PRIMARY KEY (`id`))
                                        ENGINE = InnoDB;
                                    
log
  • type - тип записи (запись в лог может принимать одно из четырех значений: info, debug, warning, error).
    Пример: $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
  • title - общий заголовок для группы логов (это может быть обобщающий заголовок для какого-нибудь автоматического процесса, или названием проекта и т.д.).
    Пример: $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
  • message - основное информационное сообщение лога.
    Пример: $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
  • ip - автоматически подставляется из массива $_SERVER['REMOTE_ADDR']
  • file_name - путь с именем файла, где была вызвана функция newLog() с записью в БД.
  • number_line - номер строки в php файле, где была вызвана функция newLog() с записью в БД.
  • date_create - время создания записи лога, запись вносится на уровне БД. Если вы создавали таблицы сами, то для MySql необходимо написать так: DATETIME NOT NULL DEFAULT now().
val_log
  • property - название свойства, можно представить это как название переменной.
  • val - значение свойсва (переменной).

Настройка логирования

Конфигурация работы логирования осуществляется в настройках параметров соединения с БД (с ключом log) GP::config([....]). Таким образом если нужна тонкая конфигурация логирования, то ее нужно осуществлять для каждой настройки соединения отдельно.

  • isWrite - писать логи в БД или игнорировать. По умолчанию значение true, это значит что в БД будут записываться логи всех четырех типов (info, debug, warning, error). false - полностью отключаем запись логов. Если необходимо, чтобы логировались только определенные типы логов, то нужно в массиве указать какие типы должны логироваться. Например мы хотим логировать только ошибки: 'isWrite' => ['error']. Или только ошибки и информационные логи: 'isWrite' => ['error', 'info']. К слову лучше указывать типы логов константами, чтобы не допустить опечатку: 'isWrite' => [GP::LOG_ERROR, GP::LOG_INFO].
  • tableLog - это массив настроек названия таблицы log и названий колонок. Ключ nameTable это название таблицы, остальные ключи это дефолтные названия колонок. Если ваша таблица или колонки называются по другому, то в значении укажите ваше название. Важно помнить, что типы колонок должны соответствовать.
    Например если ваша таблица называется не log, а mega_log и колонки вместо type - mode, а вместо title - name, то массив настроек будет таким:
                                ....
                                'tableLog' => [
                                    'nameTable' => 'mega_log',
                                    'type' => 'mode',
                                    'title' => 'name'
                                ],
                                ....
                            
  • tableValLog - это массив настроек названия таблицы val_log и названий колонок. Настраивается так же, как описано пунктом выше. Например здесь ваша таблица называется не val_log, а mega_val_log:
                                ....
                                'tableValLog' => [
                                    'nameTable' => 'mega_val_log'
                                ],
                                ....
                            

Если обобщить все вышесказанное, то массив настроек для приведенных примеров может выглядеть так:

                    GP::config([
                        'default' => [
                            ....
                            'log' => [
                                'isWrite' => [GP::LOG_ERROR, GP::LOG_INFO]
                                'tableLog' => [
                                    'nameTable' => 'mega_log',
                                    'type' => 'mode',
                                    'title' => 'name'
                                ],
                                'tableValLog' => [
                                    'nameTable' => 'mega_val_log'
                                ]
                            ]
                        ]
                    ]);
                

В любом месте можно изменить настройку isWrite и указать писать или нет в лог, а если писать, то какие конкретно типы логов. Это можно сделать с помощью функции GP::configLog($isWrite, $nameConnection = 'default'). Например мы решили что с определенного места будем писать только логи с типом error. Для этого пишим: GP::configLog([GP::LOG_ERROR]).

Описание функций

Некоторые функции используют переменную $gp, которую получаем так: $gp = GP::instance().

Формальная переменная $type в функциях обозначает тип лога и может принимать только одно из 4 значений:

  • GP::LOG_INFO значение константы: 'info'
  • GP::LOG_DEBUG значение константы: 'debug'
  • GP::LOG_WARNING значение константы: 'warning'
  • GP::LOG_ERROR значение константы: 'error'

Цветовая индикация функций: Запись в лог Вспомогательные функции для записи в лог чтение лога прочие

Функция Описание

$gp->newLog($type, $title, $message)

Основная функция, которая делает запись в лог (запись в БД в таблицу log).

  • $type - тип лога. Запись в лог может принимать одно из четырех значений: info, debug, warning или error (GP::LOG_INFO, GP::LOG_DEBUG, GP::LOG_WARNING, GP::LOG_ERROR).
  • $title - общий заголовок для группы логов (это может быть обобщающий заголовок для какого-нибудь автоматического процесса, или названием проекта и т.д.)
  • $message - основное информационное сообщение лога.
                                    $log = $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
                                

Функция возвращает экземпляр класса Log (экземпляр класса можно получить только с помощью данного метода), с которым можно дальше работать.

$log->setMessage($txt)

или

$gp->log($nameInstaceLog)->setMessage($txt)

С помощью данной функции в любой момент можно изменить сообщение лога.

                                    $log->setMessage('create backup ' . $nameFile);
                                

$log->getMessage()

или

$gp->log($nameInstaceLog)->getMessage()

Получаем сообщение лога.

                                    $message = $log->getMessage();
                                

$log->setType($type)

или

$gp->log($nameInstaceLog)->setType($type)

С помощью данной функции в любой момент можно изменить тип лога. Допустимые значения: info, debug, warning, error.

                                    $log->setType($log::LOG_ERROR);
                                

$log->getType()

или

$gp->log($nameInstaceLog)->getType()

Получаем тип лога.

                                    $type = $log->getType();
                                

$log->prop($key, $val)

или

$gp->log($nameInstaceLog)->prop($key, $val)

Расширяет запись лога дополнительными свойствами. Ограничений нет ни на количество, ни на вложенность.

  • $key - название свойства на латинице. Если необходимо указать что свойство path дочернее к свойству server, то пишем: 'server/path'
  • $val - значение свойсва.

                                    $log->prop('sizeBackup', $sizeFile)
                                        ->prop('server', $ip)
                                        ->prop('server/freePlace', $freeDiskSpace)
                                        ->prop('server/percentFreePlace', $percentFreeDiskSpace)
                                        ->prop('server/path', $path)
                                        ->prop('email', $adminMail)
                                        ->prop('email', $supportMail)
                                        ->prop('email', $vasyaMail);
                                

При каждом вызове функции prop() идет запись в таблицу val_log. После выполнения кода в БД запишется следующее:

val_log
id log_id parent_id property val
1 1 sizeBackup 10249
2 1 server 192.168.0.99
3 1 2 freePlace 23944556
4 1 2 percentFreePlace 20%
5 1 2 path /home/a1/backup/003.sql
6 1 email admin@mail.ru
7 1 email support@mail.ru
8 1 email vasya@mail.ru

Допускаются одинаковые $key, но для таких свойств невозможно будет создать потомка, если вы попытаетесь это сделать будет выброшено исключение. Дочерние свойсва допускаются только для уникальных свойств. Также вызовет ошибку, если будет указан несуществующий родитель.

                                    // Нельзя добавить потомка для не уникальных свойств
                                    ->prop('email/user', $userName)
                                    // указан несуществующий родитель
                                    ->prop('nameFile/extension', $extension)
                                

$log->save($nameInstaceLog)

Сохраняем переменную $log, для того чтобы в любом месте можно было к ней обратиться через переменную $gp.

Позволяет сохранить экземпляр класса Log (который можно получить только с помощью функции ->newLog(...)) в статический массив класса Query (экземпляр которого можно получить только с помощью функции GP::instance()). Это позволяет нам получить доступ к нашей переменной по ключу $nameInstaceLog из любого места, где есть экземпляр класса Query.

                                    class A
                                    {
                                        .....
                                        function a1() {
                                            $gp = GP::instance();
                                            // [1ый вариант]
                                            $log = $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup');
                                            $log->save('backup');
                                            // [2ой вариант]
                                            $gp->newLog(GP::LOG_INFO, 'project №001', 'create backup')
                                               ->save('backup');
                                            .....
                                        }
                                        .....
                                    }
                                    // продолжение примера снизу
                                

При сохранении переменных лога нужно следить за уникальностью $nameInstaceLog.

$gp->log($nameInstaceLog)

Позволяет получить, сохраненную ранее переменную лога по ключу $nameInstaceLog.

                                    // начало примера сверху
                                    class B
                                    {
                                        .....
                                        function b1() {
                                            $gp = GP::instance();
                                            // [1ый вариант]
                                            $log = $gp->log('backup');
                                            $log->prop('email', $catMail);
                                            // [2ой вариант] или работать через функцию log()
                                            $gp->log('backup')
                                               ->prop('email', $catMail)
                                            .....
                                        }
                                        .....
                                    }
                                

$gp->clearLog($nameInstaceLog = null)

При необходимости вы можете удалить сохраненную ранее переменную лога, указав $nameInstaceLog. Или можно удалить все сохраненные переменные, если не указывать $nameInstaceLog.

                                    // удаляем одну сохраненную переменную
                                    $gp->clearLog('backup');
                                    // удаляем все сохраненные переменные
                                    $gp->clearLog();
                                

$gp->getCanonLog($id)

Функция по id (из таблицы log) возвращает всю информацию по данному логу в древовидном виде.

В функцию передается id (или массив id) из таблицы log.

Функция возвращает все данные связанные с id, где сначала идут данные из таблицы log, а затем все данные из таблицы val_log размещаются в подмассиве properties, который имеет древовидную структуру. Данные из колонки property таблицы val_log являются ключами массива properties, а значения обязательно имеют следующую структуру:

                                    [
                                        .....
                                        'значение из property' => [
                                            'val' => [значение],
                                            'child' => []
                                        ],
                                        .....
                                    ]
                                

Т.е. каждый параметр лога (из таблицы val_log) это массив, состоящий из двух элементов:

  • val - значение которого также является массивом, даже если там одно значение.
  • child - массив с дочерними параметрами, если они отсутствуют то массив пустой.

Если в val находится json, то он никак не преобразовывается, остается просто строкой.

                                    $gp->sql('select * from log /*wh*/')
                                       ->where('/*wh*/', [
                                            ['type' => GP::LOG_INFO],
                                            ['title' => 'project №001'],
                                            ['date_create', '=', 'date' => '22.02.2022']
                                        ])
                                       ->all();
                                    // получаем массив id
                                    $id = $gp->column('id');
                                    $data = $gp->getCanonLog($id);

                                    /*  Содержимое массива $data:
                                     *  [
                                     *      [
                                     *          'id' => 1,
                                     *          'type' => 'info',
                                     *          'title' => 'project №001',
                                     *          'message' => 'create backup',
                                     *          'ip' => '172.18.0.2',
                                     *          'file_name' => '',
                                     *          'number_line' => '',
                                     *          'date_create' => '2021-09-28 13:36:08',
                                     *
                                     *          'properties' => [
                                     *              'sizeBackup' => [
                                     *                  'val' => [10249],
                                     *                  'child' => []
                                     *              ],
                                     *              'server' => [
                                     *                  'val' => ['192.168.0.99'],
                                     *                  'child' => [
                                     *                      'freePlace' => [
                                     *                          'val' => [23944556],
                                     *                          'child' => []
                                     *                      ],
                                     *                      'percentFreePlace' => [
                                     *                          'val' => ['20%'],
                                     *                          'child' => []
                                     *                      ]
                                     *                  ]
                                     *              ],
                                     *              'email' => [
                                     *                  'val' => ['admin@mail.ru', 'support@mail.ru', 'vasya@mail.ru'],
                                     *                  'child' => []
                                     *              ]
                                     *          ]
                                     *
                                     *      ],
                                     *      .....
                                     *  ]
                                     */
                                

Если передать один id, то в ответе будет ассоциативный массив со всеми данными по этому id, а если передать массив id, то функция вернет массив таких ассоциативных массивов.

$gp->getLog($id)

Данная функция является аналогом getCanonLog(), отличие в древовидной структуре массива properties, данный массив будет человекочитаемым, а если в val находится json, то он преобразуется в массив (с помощью функции json_decode()).

                                    $data = $gp->getLog(1);
                                    /*     Содержимое массива $data:
                                    *      [
                                    *          'id' => 1,
                                    *          'type' => 'info',
                                    *          'title' => 'project №001',
                                    *          'message' => 'create backup',
                                    *          'ip' => '172.18.0.2',
                                    *          'file_name' => '',
                                    *          'number_line' => '',
                                    *          'date_create' => '2021-09-28 13:36:08',
                                    *
                                    *          'properties' => [
                                    *               'sizeBackup' => 10249,
                                    *               'server' => [
                                    *                   'val' => '192.168.0.99',
                                    *                   'child' => [
                                    *                       'freePlace' => 23944556,
                                    *                       'percentFreePlace' => '20%'
                                    *                   ]
                                    *               ],
                                    *               'email' => ['admin@mail.ru', 'support@mail.ru', 'vasya@mail.ru']
                                    *          ]
                                    *      ]
                                    */
                                

$gp->createTablesForLog($table = 'all')

Если у вас в БД еще нет таблиц для логирования, то их можно создать при помощи данной функции. Причем можно создать таблицы с именами колонок, которые вы укажите в настройках лога.

$table - указывает какие таблицы создавать. По умолчанию создает все две таблицы, но можно передать значение log или val_log, тогда будет создана только одна указанная таблица.

$gp->deleteLog($numberDay, $type, $title)

Функция очищает таблицы логов.

  • $numberDay - количество дней. Будут оставлены логи, созданные за последние $numberDay дней, остальные логи будут удалены.
  • $type - точно указываем один из четырех типов лога (GP::LOG_INFO, GP::LOG_DEBUG, GP::LOG_WARNING, GP::LOG_ERROR).
  • $title - гибко ищем указанную часть значения колонки title в таблице log.
                                    // Будут удалены все ИНФОРМАЦИОННЫЕ логи, которые старше 10 дней.
                                    $gp->deleteLog(10, GP::LOG_INFO, '*');
                                

Функция возвращает массив с ключами:
log - сколько записей удалено из таблицы log.
val_log - сколько записей удалено из таблицы val_log.