HandLog - это PHP класс, благодаря которому можно быстро и удобно логировать выполнение вашего кода.
Важное замечание: HandLog создан в первую очередь для отслеживания логических ошибок и оформления структурированного вывода и сохранения сообщений, связанных с выполнением тех или иных участков кода.
Для работы требуется лишь подключить файл HandLog.php (require_once('HandLog.php');
)
-
Гибкая настройка форматирования лога
-
Подсчёт времени, затраченного на выполнение логируемых событий
-
Сохранение лога в файл в режиме дозаписи или перезаписи
-
Отслеживание размера файла лога
-
Гибкий выбор отображаемых записей
-
Собственная терминология, обеспечивающая мощную вариативность применения
Работа класса основана на следующих понятиях:
Информативная строка - заданная пользователем строка сообщения, передающаяся в действии при добавлении записи.
Тип действия - тип действия, передающийся в действии при создании записи. Может принимать следующие значения:
-
0 - харктеризует действие, как ошибку
-
1 - характеризует действие, как успех
-
2 - характеризует действие, как нейтральное
Типы действий нужны для последующего отбора записей для вывода.
Действие - в контексте класса массив, который содержит в себе информативную строку, её тип, имя события и имя лога, которым принадлежит действие. Является основным элементом взаимодействия кода пользователя с классом.
Запись - это форматированное по заданному шаблону действие, которое хранится как массив состоящий из времени добавления записи, информативной строки, типа действия и номера события, к которому принадлежит запись. Запись может быть форматирована из массива в строку по заданному шаблону для вывода.
Событие - это заданная пользователем ассоциация записей с участками кода, которые их содержат. Задаётся пользователем для структурной сортировки записей. Если не указывать, то добавляется в событие по умолчанию.
Лог - в контексте класса массив, в котором хранятся список событий и список записей. Один объект HandLog может содержать несколько логов.
- Создание массива лога
- Добавление записей
- Вывод лога
- Выбор записей согласно настройкам
- Созданией единой строки лога
- Вывод строки лога в файл и\или на экран
При написании и отладке использовался PHP 7.2.8
'note_string' => '[#time#] >> #string#' : Шаблон строки форматированной записи при выводе, #time# - заменятеся на время добавления записи, а #string# - заменяется на информативную строку.
'string_separator' => "\r\n" : Межстрочный разделитель, который будет использоваться для разделения строк записей при выводе.
'time_template' => "d-m-Y H:i:s" : Шаблон времени, для функции date(), результат работы которой заменит метку #time# при выводе.
'event_start_string' => ['[#time#]---> Event [ #event# ] started',1] : Массив, нулевым элементом которого является шаблон строки начала события, где метка #time# заменяется аналогично предыдущему шаблону, а метка #event# будет заменена на имя события. Элементом с индексом 1 является флаг отображения строки начала события при выводе, 0 - не показывать и 1 - показывать.
'event_end_string' => ['[#time#]---> Event [ #event# ] ended. Spent time: #stime# sec',1] : Массив, нулевым элементом которого является шаблон строки конца события, где метка #time# заменяется аналогично предыдущему шаблону, метка #stime# заменяется временем в секундах, затраченным на данное событие, а метка #event# будет заменена на имя события. Элементом с индексом 1 является флаг отображения строки конца события при выводе, 0 - не показывать и 1 - показывать.
'log_start_string' => ['[#time#]---> Log [ #log# ] started',1] : Массив, нулевым элементом которого является шаблон строки начала лога, где метка #time# заменяется аналогично предыдущему шаблону, а метка #log# будет заменена на имя лога. Элементом с индексом 1 является флаг отображения строки начала события при выводе, 0 - не показывать и 1 - показывать.
'log_end_string' => ['[#time#]---> Log [ #log# ] ended. Spent time: #stime# sec',1] : Массив, нулевым элементом которого является шаблон строки конца лога, где метка #time# заменяется аналогично предыдущему шаблону, метка #stime# заменяется временем в секундах, затраченным на события данного лога, а метка #log# будет заменена на имя лога. Элементом с индексом 1 является флаг отображения строки конца события при выводе, 0 - не показывать и 1 - показывать.
'select_mode' => 3 : Режим выбора записей. Может быть либо массивом либо числом. Если число:
-
0 - последняя успешная запись, первая ошибка и нейтральные;
-
1 - все успешыне записи, первая ошибка и нейтральные;
-
2 - последняя успешная запись, все ошибки и нейтральные;
-
3 - последняя успешная запись перед первой ошибкой и нейтральные.
Если массив, то будут выбираться те, чьи типы указаны; пример: [0,2] - выбираются ошибки и нейтральные.
'default_event' => 'Main' : Названия события по умолчанию.
'default_log' => 'Default' : Название лога по умолчанию. Замечание: если при создания объекта класса передать имя, то оно заменит данное значение.
'echo_mode' => 2 : Режим вывода записей.
-
0 - прямое сохранение в файл
-
1 - вывод лога на экран
-
2 - вывод лога на экран и сохранение в файл
'log_order' => 0 : Режим порядка отображения записей при выводе.
-
0 - сначала новые записи
-
1 - сначала старые записи
'filename' => '#log#_lastLog.txt' : Шаблон имени файла последнего лога, где метка #log# будет заменена на имя лога.
're_filename' => 'logsave_#log#_#time#.txt' : Шаблон имени файла, в который переименуется файл лога при переполнении. Метка #log# будет заменена на имя лога, а метка #time# будет заменена на время переименования фалйа по шаблону 'refile_time_template'.
'refile_time_template' => "d.m.Y_H-i-s" : Формат времени для функции date(), которая заменит метку #time# в имени файла лога при переполнении.
'file_size_limit' => 5*1024*1024 : Размер файла лога в байтах, при превышении которого файл лога будет переименован по шаблону 're_filename'.
'dir' => 'Data/Logs' : Директория, в которую будут сохраняться фалы логов. Значение '' означет запись в текущую директорию.
'rewrite_mode' => 1 : Режим записи лога в файл.
-
0 - дозапись в начало либо конец файла в зависимости от 'log_order'
-
1 - перезапись файла
'line_break_html' => 1 : Флаг замены символов перевода строки( \r\n ) в формат html ( <br>
) для корректного отображения в браузере при выводе(при этом в файл записывается версия без замены).
'datum_filename' => 'handlog_datum.txt' : Имя файла, в который выгрузится data, содержащая все логи в полном составе, при вызови функции класса datum_load_out($to).
-
new HandLog($logname)
- создаёт объект класса, в качестве $logname(необязательный, иначе используется имя изsettings['default_log']
) передаётся имя лога, который будет использоваться для добавления записей по умолчанию -
new_log($logname)
- создаёт лог с именем $logname(обязательный) -
new_event($eventname,$logname)
- создаёт событие $eventname(обязательный) в логе $logname(необязательный, иначе используется имя изsettings['default_log']
) -
new_note(array $action)
- создаёт запись, $action(обязательный) - массив с элементами[0=>строка действия, 1=>тип действия, 2=>имя события, 3=>имя лога]
; имя события и имя лога - не обязательные, чтобы передать имя лога и использовать событие по умолчанию, используется символ "#", пример:$log->new_note(['Action',0,'#','Logname']);
-
echo_log($logname,$events)
- осуществляет вывод записей событий $events(необязательный, массив, содержащий имена событий) из лога с именем $logname(необязательный, иначе используется имя изsettings['default_log']
), при вызове без параметров выводятся все события из лога по умолчанию -
settings['Имя настрйоки'] = значение
- можно изменять значения настроек в процессе логирования, например можно вывести записи в режиме выбора "0"
$log->settings['select_mode'] = 0;
$log->echo_log();
,а затем поменять режим выбора на "3"
$log->settings['select_mode'] = 3;
$log->echo_log();
и посмтореть разницу.
Принцип действия остальных функций можно посмотреть непосредственно в прокомментированной версии класса.
Такой PHP код:
require_once('HandLog/HandLog.php'); /* подключаем файл класса */
$log = new HandLog('LogName'); /* создаём объект класса(отсчёт общего времени начинается именно с этого момента) */
$flag1 = 5*5;
if($flag1==25){
$log->new_note(['Multiplying 5 by 5 equals 25',1,'Event Multiplication']); /* пример добавления записи в лог, ОБЯЗАТЕЛЬНЫ строка и тип действия, то есть можно передавать массив с количеством элементов от 2 до 4, 3-ий по счёту(начиная с единицы) - имя события, 4-ый - имя лога */
}else{
$log->new_note(['Multiplying 5 by 5 is not equal to 25',0,'Event Multiplication']); /*
}
sleep(1); /* односекундное бездействие, не влияющее на учёт времени каких-либо событий(так как после него не добавляются записи в "Event Multiplication", а до него добавляются записи в "Event Substraction" ), но влияющее на общее время, так как после него ещё добавляются записи */
$flag2 = 10-8;
if($flag2==2){
$log->new_note(['Subtraction 8 of 10 is 2',1,'Event Substraction']);
}else{
$log->new_note(['Subtracting 8 from 10 is not equal to 2',0,'Event Substraction']);
}
sleep(1); /* это бездействие войдёт в событие "Event Substraction", так как в это событие добавляются записи до и после */
$flag3 = 7-7;
if($flag3==1){
$log->new_note(['Subtraction 7 of 7 is 1',1,'Event Substraction']);
}else{
$log->new_note(['Subtracting 7 from 7 is not equal to 1',0,'Event Substraction']);
}
$log->new_note(['Because subtracting 7 from 7 is 0',2,'Event Substraction']);
sleep(1); /* это бездействие войдёт в событие "Event Substraction", так как в это событие добавляются записи до и после */
$flag4 = 11-7;
if($flag4==4){
$log->new_note(['Subtraction 7 of 11 is 4',1,'Event Substraction']);
}else{
$log->new_note(['Subtracting 7 from 11 is not equal to 1',0,'Event Substraction']);
}
$log->new_note(['Subtracting 7 from 11 is 4 but false action appeared earlier',2,'Event Substraction']); /* Добавление записи типа "2"; данный тип записей участвует в выводе большинства режимов */
$log->echo_log('LogName'); /* Выводим лог, под выводом подразумевается как запись(или дозапись) в файл, так и вывод непосредственно на экран посредством echo */
echo 'Select mode: '.$log->settings['select_mode']; /* Показываем используемый режим */
С таким массивом настроек:
public $settings = [
'note_string' => '[#time#] >> #string#',
'string_separator' => "\r\n",
'time_template' => "d-m-Y H:i:s",
'event_start_string' => ['[#time#]---> Event [ #event# ] started',1],
'event_end_string' => ['[#time#]---> Event [ #event# ] ended. Spent time: #stime# sec',1],
'log_start_string' => ['[#time#]---> Log [ #log# ] started',1],
'log_end_string' => ['[#time#]---> Log [ #log# ] ended. Spent time: #stime# sec',1],
'select_mode' => 3,
'default_event' => 'Main',
'default_log' => 'Default',
'echo_mode' => 2,
'log_order' => 0,
'filename' => '#log#_lastLog.txt',
'refile_time_template' => "d.m.Y_H-i-s",
're_filename' => 'logsave_#log#_#time#.txt',
'file_size_limit' => 5*1024*1024,
'dir' => 'Logs',
'rewrite_mode' => 1,
'line_break_html' => 1,
'datum_filename' => 'handlog_datum.txt'
];
Даст примерно следующий результат:
[25-12-2018 19:59:21]---> Log [ LogName ] ended. Spent time: 3.00211596 sec
[25-12-2018 19:59:21]---> Event [ Event Substraction ] ended. Spent time: 2.00038195 sec
[25-12-2018 19:59:21] >> Subtracting 7 from 11 is 4 but false action appeared earlier
[25-12-2018 19:59:20] >> Because subtracting 7 from 7 is 0
[25-12-2018 19:59:20] >> Subtracting 7 from 7 is not equal to 1
[25-12-2018 19:59:19] >> Subtraction 8 of 10 is 2
[25-12-2018 19:59:19]---> Event [ Event Substraction ] started
[25-12-2018 19:59:18]---> Event [ Event Multiplication ] ended. Spent time: 0.00001597 sec
[25-12-2018 19:59:18] >> Multiplying 5 by 5 equals 25
[25-12-2018 19:59:18]---> Event [ Event Multiplication ] started
[25-12-2018 19:59:18]---> Log [ LogName ] started
Select mode: 3
В данном примере, показывается, как работает 3-ий режим выбора записей: в случае возникновения записи типа "0", показываются записи типа "2" и последняя запись типа "1" предшествующая ошибке. В случае, когда нет записей ошибок, выбирается просто последняя успешная запись и записи типа "2".
Такой PHP код:
require_once('HandLog/HandLog.php');
$log = new HandLog(); /* cоздаём объект класса с именем лога по умолчанию */
$event1 = 'Event 1';
for($i=0;$i<6;$i++){
$type = rand(0,2);
$log->new_note(['Action '.$i.' Type: '.$type,$type,'Event 1']);
}
for($i=0;$i<6;$i++){
$type = rand(0,2);
$log->new_note(['Action '.$i.' Type: '.$type,$type]);
}
$log->echo_log();
echo 'Select mode: <br>';
print_r($log->settings['select_mode']);
С таким массивом настроек:
public $settings = [
'note_string' => '[#time#] >> #string#',
'string_separator' => "\r\n",
'time_template' => "d-m-Y H:i:s",
'event_start_string' => ['[#time#]---> Event [ #event# ] started',1],
'event_end_string' => ['[#time#]---> Event [ #event# ] ended. Spent time: #stime# sec',1],
'log_start_string' => ['[#time#]---> Log [ #log# ] started',1],
'log_end_string' => ['[#time#]---> Log [ #log# ] ended. Spent time: #stime# sec',1],
'select_mode' => [1,2], /* так, как установлен массив, то для вывода будут выбираться все записи, чьи типы содержатся в массиве */
'default_event' => 'Main',
'default_log' => 'Default',
'echo_mode' => 2,
'log_order' => 0,
'filename' => '#log#_lastLog.txt',
'refile_time_template' => "d.m.Y_H-i-s",
're_filename' => 'logsave_#log#_#time#.txt',
'file_size_limit' => 5*1024*1024,
'dir' => 'Logs',
'rewrite_mode' => 1,
'line_break_html' => 1,
'datum_filename' => 'handlog_datum.txt'
];
Даст примерно следующий результат:
[25-12-2018 22:34:34]---> Log [ Default ] ended. Spent time: 0.00009799 sec
[25-12-2018 22:34:34]---> Event [ Main ] ended. Spent time: 0.00002599 sec
[25-12-2018 22:34:34] >> Action 5 Type: 2
[25-12-2018 22:34:34] >> Action 4 Type: 1
[25-12-2018 22:34:34] >> Action 3 Type: 2
[25-12-2018 22:34:34] >> Action 2 Type: 2
[25-12-2018 22:34:34]---> Event [ Main ] started
[25-12-2018 22:34:34]---> Event [ Event 1 ] ended. Spent time: 0.00003099 sec
[25-12-2018 22:34:34] >> Action 4 Type: 1
[25-12-2018 22:34:34] >> Action 2 Type: 2
[25-12-2018 22:34:34] >> Action 1 Type: 1
[25-12-2018 22:34:34] >> Action 0 Type: 1
[25-12-2018 22:34:34]---> Event [ Event 1 ] started
[25-12-2018 22:34:34]---> Log [ Default ] started
Select mode:
Array ( [0] => 1 [1] => 2 )