Yii надає гнучкий та розширюваний функціонал протоколювання. Повідомлення можна класифікувати відповідно до рівня протоколювання і типом повідомлень. Використовуючи фільтри за рівнем та категорією, можна направити потік повідомлень у файли, електронну пошту, вікно браузера і т.д.
Повідомлення може бути запротокольовано шляхом виклику Yii::log або Yii::trace. Різниця між ними полягає у тому, що останній пише в лог тільки тоді, коли додаток працює у режимі відладки.
Yii::log($message, $level, $category);
Yii::trace($message, $category);
Для внесення повідомлення у лог, необхідно вказати категорію і рівень повідомлення.
Категорія представляє собою рядок формату xxx.yyy.zzz
, що дуже схоже з форматом представлення
псевдоніма шляху. Наприклад, якщо повідомлення додається у лог в CController,
ми можемо використовувати категорію system.web.CController
. Рівень повідомлення може мати одне із наступних значень:
trace
: цей рівень використовується методом Yii::trace. Він призначений для відстеження процесу виконання додатка у ході розробки;
info
: цей рівень призначений для протоколювання інформації загального характеру;
profile
: даний рівень використовується для профілювання (вимірювання) продуктивності;
warning
: цей рівень призначений для повідомлень-попереджень;
error
: цей рівень використовується для повідомлень про критичні помилки.
Повідомлення, що протоколюються із використанням Yii::log або Yii::trace, зберігаються у памʼяті. Як правило, нам потрібно або відобразити їх у вікні браузера, або зберегти у файлі, відправити електронним листом та ін. Напрямок повідомлень у різні місця призначення називається маршрутизацією повідомлень.
В Yii за маршрутизацію повідомлень відповідає компонент додатка CLogRouter. Цей компонент керує безліччю так званих маршрутів повідомлень. Кожен маршрут представляє одне місце призначення потоку повідомлень. Повідомлення, що направляються на той чи інший маршрут, можна відфільтрувати у залежності від їх рівня і типу.
Для того, щоб скористатися маршрутизацією повідомлень, нам необхідно встановити і довантажити заздалегідь компонент додатка CLogRouter. Крім того, необхідно налаштувати властивість routes цього компонента, вказавши маршрути повідомлень, які передбачається використовувати. Нижче наведено приклад необхідної конфігурації додатка:
array(
…
'preload'=>array('log'),
'components'=>array(
…
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'trace, info',
'categories'=>'system.*',
),
array(
'class'=>'CEmailLogRoute',
'levels'=>'error, warning',
'emails'=>'admin@example.com',
),
),
),
),
)
У прикладі вище, у нас є два маршрути повідомлень. Перший - CFileLogRoute - зберігає повідомлення у папці додатка
для тимчасових файлів runtime
. Зберігаються тільки повідомлення з рівнем trace
або info
і чия категорія починається з system.
.
Другий маршрут - CEmailLogRoute - відправляє повідомлення на вказану електронну адресу.
Відправляються тільки повідомлення рівня error
або warning
.
Починаючи з Yii версії 1.1.13 можна виключати певні категорії:
'routes'=>array(
array(
'class'=>'CEmailLogRoute',
'levels'=>'error, warning',
'except'=>'system.CModule.*' // відправляємо поштою все, окрім повідомлень від CModule
'emails'=>'admin@example.com',
),
array(
'class'=>'CWebLogRoute',
'categories'=>'system.db.*',
'except'=>'system.db.ar.*', // відображаємо все, що стосується бази даних, але не стосується AR
),
В Yii доступні для використання наступні маршрути повідомлень:
array(
......
'preload'=>array('log'),
'components'=>array(
......
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CProfileLogRoute',
'report'=>'summary',
// Відображає час виконання кожного відміченого блоку кода.
// Значення "report" також можна вказати як "callstack".
),
...інші маршрути...
),
),
),
)
Інформація: Маршрутизація повідомлення відбувається у кінці кожного поточного циклу обробки запиту, у момент, коли викликається подія onEndRequest. Для переривання процесу обробки поточного запиту, використовуйте метод CApplication::end() замість
die()
абоexit()
. CApplication::end() викликає подію onEndRequest, що дозволяє коректно запротоколювати повідомлення.
Як вже згадувалося вище, повідомлення можна відфільтрувати по їх рівню і типу до того, як вони будуть направлені тим чи іншим маршрутом. Це здійснюється шляхом налаштування властивостей levels та categories відповідного маршруту. Якщо необхідно вказати кілька рівнів або типів, значення повинні бути розділені комами.
Оскільки типи повідомлень вказуються у форматі xxx.yyy.zzz
, ми можемо сприймати їх як ієрархію типів.
Зокрема, ми говоримо, що xxx
є батьком xxx.yyy
, а останній у свою чергу є батьком для xxx.yyy.zzz
.
Тому для вказівки типу xxx
, а також всіх його типів-нащадків можна використовувати вираз xxx.*
.
Ми можемо зберігати додаткову інформацію, таку як визначені змінні PHP ($_GET
, $_SERVER
),
ID сесії, імʼя користувача і т.д. Для цього необхідно задати необхідний фільтр у властивості CLogRoute::filter.
До складу фреймворку входить зручний клас CLogFilter, який може бути використаний у якості фільтра у більшості випадків.
За замовчуванням, CLogFilter буде записувати повідомлення разом з такими змінними, як $_GET
и $_SERVER
,
які зазвичай містять цінну системну інформацію. можна налаштувати CLogFilter таким чином,
щоб перед кожним повідомленням записувати ID сесії, імʼя користувача та інші дані,
які можуть полегшити пошук по великій кількості повідомлень.
Наступні налаштування включають запис контексту повідомлень. У кожного журнального маршруту може бути заданий свій фільтр. За замовчуванням ніякого фільтра не задано.
array(
…
'preload'=>array('log'),
'components'=>array(
…
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error',
'filter'=>'CLogFilter',
),
…other log routes…
),
),
),
)
Yii підтримує журналювання інформації стека виклику у повідомленнях, що протоколюються шляхом виклику Yii::trace.
За замовчуванням, дана особливість відключена, тому що знижує продуктивність.
Для її використання, необхідно просто визначити константу YII_TRACE_LEVEL
на початку вхідного скрипта
(до включення файлу yii.php
) цілим числом, більшим від нуля.
Тоді Yii буде додавати у кожне трасуюче повідомлення імʼя файлу і номер рядка стека виклику, у яких був зроблений виклик коду.
Число YII_TRACE_LEVEL
визначає кількість шарів кожного стека виклику, яке повинно бути записано.
Ця інформація особливо корисна на стадії розробки, тому що може допомогти нам визначити місця,
у яких викликаються трасуючі повідомлення.
Для цілей вимірювання продуктивності використовується спеціальний тип повідомлень. Його можна використовувати для вимірювання часу виконання деякого блоку коду та визначення вузьких місць у продуктивності.
Для того, щоб виміряти продуктивність, необхідно вказати ту частину коду, виконання якої буде відслідковуватися. Використовуючи такі методи, ми відзначаємо початок і кінець кожного вимірюваного блоку коду:
Yii::beginProfile('blockID');
…блок профільованого коду…
Yii::endProfile('blockID');
де blockID
— це унікальний ідентифікатор блоку коду.
Зверніть увагу, що блоки коду повинні мати коректну вкладеність, тобто вони не можуть перетинатися один з одним. Вони або йдуть паралельно, або один блок повністю включає інший.
Для того, щоб побачити результат профілювання, нам буде потрібно встановити компонент додатка CProfileLogRoute, відповідальний за відповідний маршрут протоколювання. Тут все аналогічно роботі із простими маршрутами повідомлень. Маршрут CProfileLogRoute відобразить результати вимірювання продуктивності внизу поточної сторінки.
Профілювання особливо корисне при роботі із базою даних, так як SQL-запити часто є найвужчим місцем продуктивності додатка.
Незважаючи на те, що ми можемо вкласти у потрібні місця beginProfile
та endProfile
для того, щоб заміряти час, витрачений на кожен SQL-запит, Yii надає
більш зручне рішення даної проблеми.
Встановивши у налаштуваннях додатка CDbConnection::enableProfiling у true
,
ми отримаємо профілювання всіх виконуваних SQL-запитів. Отримані результати можна вивести за допомогою вищезгаданого CProfileLogRoute,
що показує скільки часу зайняв той чи інший SQL-запит .
Для виведення загальної кількості запитів і загального часу виконання можна використовувати CDbConnection::getStats().