Створюємо статистику для сайту своїми руками на
Практично у кожного власника сайту в якийсь момент виникає бажання дізнатися якісь статистичні дані про своїх відвідувачів. Скільки відвідувачів заглядає на сайт, як довго вони знаходяться на сайті, які сторінки дивляться, звідки приходять і т.д. І, в принципі, для отримання подібної інформації вистачає різноманітних безкоштовних (і не дуже) сервісів типу top.mail.ru або www.spylog.com, а так само парсеров логів веб серверів. Але всі ці служби і сервіси мають чимало недоліків - наприклад втрата інформації через недоступність онлайн служби або блокування користувачем зображень в своєму браузері або ж надмірність лог файлів веб сервера і неможливість більш-менш однозначно за допомогою парсинга лог файлів визначити сесію користувача. А крім того вони абсолютно нездатні дати відповіді на якісь специфічні питання, наприклад, на питання «показати список користувачів, які прийшли з пошукових систем і зареєструвалися в сесію приходу». Або ж «показати все сесії конкретного користувача за весь період часу». Що призводить поступово до думки про створення власної системи логування та набору звітів для отримання потрібної статистики.
У якийсь момент встала подібне завдання і переді мною. Після серйозного редизайну сайту замовник зажадав статистику, пов'язану з урахуванням відвідувачів з пошукових систем в розрізі їх реєстрацій на сайті і здійснення, припустимо, покупок. А, крім того, замовника дуже цікавили моменти як добре і швидко пошукові системи пройдуться по сайту і покладуть його сторінки в свій індекс. Відповідно довелося мені зайнятися створенням системи логування відвідувань сайту.
База даних

Невелике пояснення - як я раніше вже згадував в списку звітів по відвідувачах у мене важливу роль грали зареєстровані користувачі. Що і спонукало мене додати стовпець UserID, куди буде записуватися ім'я користувача якщо логіруется аутентіфіцированний запит. І хоча я, наприклад, вважаю за краще використовувати для ідентифікації користувача ціле число (identity ключ соотв. Таблиці бази) в таблиці Session це поле має тип varchar для максимальної сумісності. Крім того в сесії зберігається інформація про першій і останній сторінках сесії, а так само про дату початку і закінчення сесії для зручності побудови звітів по точках входу / виходу та часу. Ну а з кожним запитом сторінки я зберігаю інформацію про те, аутентифікований користувач і чи є цей запит постбеком.
Для запису запосіли в БД використовуються дві не найскладніші процедури:
Процедура p_SessionStart, як мені здається, не вимагає ніяких додаткових пояснень, а для процедури p_DoRequest зроблю коротке зауваження, що крім логування самого запиту на сторінку вона так само змінює деякі значення сесії.
На цьому поки що робота зі створення бази даних завершена і можна переходити до написання програмного коду для логування заходів користувачів на сайт.
модуль логування
Програмну частину системи логування відвідувань сайтів я вирішив зробити у вигляді HTTP модуля. Передумови очевидні - система логування повинна працювати з сайтами без зміни їх коду, просто налаштовуватися і обробляти всі asp.net запити. Знову таки код цього модуля простий до неподобства і в сумі займає ледь за сотню рядків коду.
Так як вся настройка роботи модуля буде вестися за допомогою конфігураційного файлу, то найоптимальнішим рішенням для цього буде створення своєї секції в конфігураційного файлу для модуля. Модулю для своєї роботи потрібна рядок підключення до БД, ім'я сайту (необов'язково) і місце зберігання ідентифікатора сесії користувача (asp.net сесія або куки, за замовчуванням куки). Відповідно код структури параметрів модуля:
Сама ж секція конфігураційного файлу суть клас, який реалізує інтерфейс System.Configuration.IConfigurationSectionHandler. Цей інтерфейс містить єдиний метод Create, який повинен повернути об'єкт. Я не буду довго розповідати що і як тут необхідно зробити (це можна прочитати і в MSDN) і просто приведу код класу:
Як бачите нічого складного в вищенаведеному коді немає - він всього лише Новомосковскет параметри з XmlNode і заповнює клас параметрів модуля. Для того, щоб додати створену вище секцію в файлі конфігурації в секції
А отримати ці параметри в коді класу можна за допомогою наступного рядка коду:
Для логування запиту користувача використовується метод SiteStatsBLL.Request (), який в свою чергу при необхідності викликає метод SiteStatsBLL.SessionStart () для старту нової сесії. Обидва методи всього лише викликають відповідні процедури, що зберігаються.
Метод SiteStatsBLL.Request () я викликаю в обробнику події HttpApplication. PostRequestHandlerExecute. У момент спрацьовування цієї події обробка стнаніци завершена і сторінка готова до відправки клієнтові, але сесія ще сущетвует (у нас же є опція збереження SessionID в сесії). І вся задача HTTP модуля полягає в тому, щоб при настанні цієї події викликати метод логування запиту:
Усе. процес створення модуля логування запитів до сайту завершено. Тепер для того, щоб почати вести логи для якогось сайту досить переписати вийшла збірку в підкаталог bin цього сайту і внести в файл web.config следуюшие зміни.
1. Додати опис секції в розділ
2. В той же розділ додати саму секцію siteStats:
3. У секцію
Робота зроблена і тепер все asp.net запити до сайту будуть Залогуватися. Але перш, ніж я закінчу цю статтю, я хотів би ще розповісти про деякі додаткових маніпуляціях над зберігаються даними.
Пошукові роботи та Спрямування
Щоб не обтяжувати Новомосковсктеля довгими міркуваннями про те, які існують роботи і який робот кому служить я приведу відразу невеликий список масок враховуються мною юзерагентов роботів:
Останній рядок у цьому списку звичайно досить таки радикальна, але цих роботів стільки людська думка наплодила - благо, що хоч вони часто зізнаються чесно, що вони боти :).
Крім обробки «непользовательскіх» заходів потрібно також зробити обробку рефералів - з якого сайту / пошукової системи прийшов відвідувач і які пошукові слова він використовував в разі приходу з пошукової системи. І тут знову не обійтися без додаткових таблиць - списку пошукових систем і для списку реферральний сайтів. Ну а крім того необхідна таблиця для зберігання пошукових фраз. І, звичайно, всі ці таблиці будуть пов'язані з таблицею Session.
Таблиці для сайтів і пошукових фраз нічого з себе особливого не представляють - це звичайні довідники, в які в разі потреби будуть додаватися нові значення.
Більш цікава таблиця пошукових систем - в ній крім назви пошукової системи знадобиться також зберігати інформацію про масці імені сайту, а також інформацію про те, де в рядку реферрала зберігається пошукова фраза. Зазвичай пошукова фраза міститься в якомусь конкретному параметрі URL, але бувають і особливо "просунуті" індивідууми, засовує її в структуру каталогів URL. Але і на їх фоні виробиться AOL, в разі пошуку з головної сторінки передає пошукову фразу в рядку запиту в зашифрованому вигляді. Благо хоч в іншому параметрі, що дозволяє спростити облік пошукових фраз.
Нижче представлений приблизний довідник пошукових сайтів для створюваної системи статистики.
Параметр пошукової фрази
Озброївшись усім вищевикладеним можна приступати до реалізації обліку заходів різних роботів і попередній обробці реферральний заходів.
розширення модуля
Крім згаданих мною вище 4-х нових таблиць (Sites, Bots, SearchEngines і Keywords) змінюється тільки таблиця Session, в якій додаються 4 поля, що посилаються на додані таблиці:

Ну і відповідним чином змінюється процедура старту сесії:
Насправді заповнювати додаткове дані про роботів, Спрямування і пошукових системах можна 2-ма шляхами - в момент додавання запису в БД або окремої збереженої процедурою, обробної вже збережені в базу дані. Відповідно у другому випадку зміна процедури, що для додавання запису про сесії не потрібно. І, так як цей шлях трохи простіше, я спочатку покажу його реалізацію.
Обробка логів в БД
Як я вже згадав, ця процедура повинна обробляти вже введені дані. У мене це були дані, введені за якийсь останній відрізок часу (конкретніше - за останню годину). Відповідно одним з параметрів цієї процедури буде дата / час, з якої потрібно обробляти дані. І, крім того, також в неї передається параметр яким чином обробляти записи роботів - пов'язувати їх або ж видаляти
Обробка записів роботів проста до примітивізму. При збереженні логів заходів роботів робиться 2 простих update по зв'язці таблиць Session і Bots (другий запит потрібен для того, щоб обробити "нез'ясованих" роботів, милостиво зволив повідомити про себе, що вони таки роботи). При очищенні ж бази від записів заходів роботів - дві не менш простих команди delete.
Чи не більшу складність являє собою і запит щодо визначення заходів з пошукових систем
Ну і останній момент - виділення пошукових запитів з уже знайдених парафій з пошукових систем. Для цього якраз таки і потрібно поле KeywordMask - все, що буде знайдено в рядку між підрядком їх цього поля і символом (Або до кінця рядка, якщо такого символу більше немає) вважається пошуковою фразою. При цьому, як я вже згадав раніше, запити, в яких пошукові фрази не виділяються параметрами URL, не враховуються (для запитів з таких пошукових систем значення KeywordMask одно /).
Все, обробка логів на стороні сервера завершена. Тепер досить викликати тільки що написану процедуру, наприклад, раз на годину і логи будуть готові до подальшого використання.
Але не завжди це може бути зручно. Якщо необхідна система статистики реального часу, звіти по якій повинні давати вірні дані за будь-який проміжок, то тут не обійтися без синхронізації запису логів з їх обробкою. І в цьому випадку може стати в нагоді винос цієї логіки в програмний код.
Модернізація програмного коду
Для цього необхідно в принципі реалізувати ту ж саму логіку виділення запитів пошукових роботів, реферральний парафій і парафій з пошукових систем в уже написаному раніше модулі.
У конфігурацію модуля додамо 2 додаткових параметра - ParseAddData для завдання факту додаткової обробки запитів користувачів і PersistBots для вказівки чи зберігати в базі запити роботів. Для цього в клас SiteStatsSettings також додамо рядки
Ну а в код методу Create класу SiteStatsConfigHandler відповідно додамо їх ініціалізацію
Тепер конфігураційна секція модуля у файлі web.config буде виглядати приблизно так.
Для пошуку і визначення ідентифікаторів роботів і пошукових систем в коді SiteStatsBLL додаються 2 статичних поля типу SortedList для зберігання списку шаблонів роботів і пошукових сайтів і статичний конструктор для заповнення цих списків. При цьому для зручності пошуку в цих списках будемо зберігати не самі маски для пошуків, а відразу ж створимо відповідні екземпляри класу Regex. І так як пошук ведеться до першого знайденого значення не потрібно забувати про те, що порядок розміщення масок важливий (пошук по масці "bot" повинен проводитися в останню чергу)
У код методу SessionStart додамо блок для визначення ідентифікаторів робота і пошукової системи, а так само пошукової фрази і сайту-реферрала
Зверніть увагу, що в разі, якщо система налаштована на ігнорування запитів пошукових роботів, то цей метод поверне -1. Відповідно в методі Request додатково потрібно зробити перевірку значення SessionID перед записом інформації про запит до бази (відразу після секції визначення SessionID).
Ну і, нарешті, в тому ж методі SessionStart потрібно додати код для передачі при необхідності знайдених значень в збережену процедуру
Все, тепер робота зі створення модуля логування точно завершена :). У доданому до статті архіві можна знайти mdf файл бази даних і весь вихідний код. Ну а я ж в наступній статті постараюся додати життя в цей проект і опишу створення набору звітів для отримання більш улюблених керівництвом і / або замовниками картинок і таблиць з використанням Reporting Services.