Установка и настройка AWStats для Nginx

AWStats (он же Advanced Web Statistics) - аналитический инструмент, который собирает и анализирует информацию в логах сервера и предоставляет полученные данные в виде таблиц и графиков. С помощью AWStats можно анализировать логи web-сервера, ftp или почтового сервера. Мы будем собирать статистику только о посещениях веб-сайта.

Исторически так сложилось, что AWStats заточен на работу с логами Apache (httpd). Логи nginx, как написано в FAQ самого инструмента, является "exotic web log format". В этой статье мы рассмотрим, как заставить AWStats читать логи Nginx'а.

Установка AWStats в Centos 8

Сразу оговорюсь - в репозиториях Epel Awstats есть, но просто так его поставить не получится, т.к. версия из репозитория собрана с использованием Perl 5.24, а в RHEL8 используется Perl 5.26 по умолчанию. Конечно, можно переключиться на версию Perl 5.24, но это повлечёт за собой кучу ненужных телодвижений, связанных со сменой версии других приложений, собранных в Perl 5.26 и включенных в поставку операционной системы.

Перед установкой проверим , что в системе установлен wget

yum install wget

После этого идём на официальную страницу AWStats на SourceForge.NET и копируем ссылку на скачивание RPM-пакета последней версии awstats и скачиваем пакет на сервер

wget https://tenet.dl.sourceforge.net/project/awstats/AWStats/7.8/awstats-7.8-1.noarch.rpm

 После завершения загрузки устанавливаем пакет AWStats, соглашаясь на установку всех зависимостей (у меня их было 139 на 17 МБ)

yum localinstall awstats-7.8-1.noarch.rpm

Настройка Awstats

После завершения установки переходим к настройкам анализа лог-файлов. Все основные конфигурационные файлы AWStats находятся в каталоге /usr/local/awstats.

Мы не будем трогать стандартный конфиг, а создадим копию, для своего сайта

cp /etc/awstats/awstats{.model,.my.site}.conf

Откроем наш конфиг для редактирования

nano /etc/awstats/awstats.my.site.conf

В конфигурационном файле нас интересуют следующие параметры:

LogFile
Путь к файлу логов, который мы будем анализировать. У меня логи находтся по пути /var/www/user/log/my.site.acces.log, поэтому конфиг выглядит следующим образом:
LogFile="/var/www/user/log/my.site.acces.log"
LogType
Это тип логов, которые мы планируем анализировать. По умолчанию установлено значение W, что означает WEB-logs. Это значение мы не трогаем (если LogType установлено другое значение, то меняем его на W)
SiteDomain и HostAliases
Тут указываем доменное имя нашего сайта и его псевдонимы (адреса, по которым к сайту можно обратиться)
В поле HostAliases можно указать регулярное выражение, для сбора статистики, например, с поддоменов
SiteDomain="my.site"
HostAliases="localhost 127.0.0.1 REGEX[my\.site$]"
DirData
Папка, в которой будут храниться файлы статистики
DirData="/var/www/user/awstats/my.site/"
LogFormat
Формат записи логов - самый интересный параметр, т.к. AWStats не умеет читать стандартные логи nginxa, да и на севрерах часто используют собственный формат. Об этом параметре мы поговорим ниже.

LogFormat Awstats для Nginx

По умолчнию формат логов Nginx выглядит следующим образом:

log_format  main    '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

Посмотреть его можно по пути /etc/nginx/nginx.conf

Сам же, записанный лог, в таком формате, выглядит так:

8.8.8.8 - - [31/May/2021:22:06:25 +0300] "GET /templates/template/i/footer-social2.png HTTP/2.0" 200 4435 "https://my.site/templates/template/css/style.css?ver=1.3.19" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"

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

#   %host             Client hostname or IP address (or Sender host for mail log)
#   %host_r           Receiver hostname or IP address (for mail log)
#   %lognamequot      Authenticated login/user with format: "john"
#   %logname          Authenticated login/user with format: john
#   %time1            Date and time with format: [dd/mon/yyyy:hh:mm:ss +0000] or [dd/mon/yyyy:hh:mm:ss]
#   %time2            Date and time with format: yyyy-mm-dd hh:mm:ss
#   %time3            Date and time with format: Mon dd hh:mm:ss or Mon dd hh:mm:ss yyyy
#   %time4            Date and time with unix timestamp format: dddddddddd
#   %time5            Date and time with format iso: yyyy-mm-ddThh:mm:ss, with optional timezone specification (ignored)
#   %time6            Date and time with format: dd/mm/yyyy, hh:mm:ss
#   %methodurl        Method and URL with format: "GET /index.html HTTP/x.x"
#   %methodurlnoprot  Method and URL with format: "GET /index.html"
#   %method           Method with format: GET
#   %url              URL only with format: /index.html
#   %query            Query string (used by URLWithQuery option)
#   %code             Return code status (with format for web log: 999)
#   %bytesd           Size of document in bytes
#   %refererquot      Referer page with format: "http://from.com/from.htm"
#   %referer          Referer page with format: http://from.com/from.htm
#   %uabracket        User agent with format: [Mozilla/4.0 (compatible, ...)]
#   %uaquot           User agent with format: "Mozilla/4.0 (compatible, ...)"
#   %ua               User agent with format: Mozilla/4.0_(compatible...)
#   %gzipin           mod_gzip compression input bytes: In:XXX
#   %gzipout          mod_gzip compression output bytes & ratio: Out:YYY:ZZpct.
#   %gzipratio        mod_gzip compression ratio: ZZpct.
#   %deflateratio     mod_deflate compression ratio with format: (ZZ)
#   %email            EMail sender (for mail log)
#   %email_r          EMail receiver (for mail log)
#   %virtualname      Web sever virtual hostname. Use this tag when same log
#                     contains data of several virtual web servers. AWStats
#                     will discard records not in SiteDomain nor HostAliases
#   %cluster          If log file is provided from several computers (merged by
#                     logresolvemerge.pl), use this to define cluster id field.
#   %extraX           Another field that you plan to use for building a
#                     personalized report with ExtraSection feature (See later).
#   If your log format has some fields not included in this list, use:
#   %other            Means another not used field
#   %otherquot        Means another not used double quoted field
#   If your log format has some literal strings, which precede data fields, use
#   status=%code      Means your log files have HTTP status logged as "status=200"
#   Literal strings that follow data field must be separated from said data fields by space.

Руководствуясь этими данными составим LogFormat AWStats для Nginx

LogFormat="%host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"
Обратите внимание!

Последний параметр из log_format Nginx'а $http_x_forwarded_for в лог не попадает (я, честно говоря, не понимаю, для чего его вообще сюда вписали по умолчанию), поэтому LogFormat для AWStats я закончил на UserAgent'е

Сбор статиситки Awstats из Nginx

Теперь, когда все настройки завершены, необходимо запустить сбор статиситки из логов:

/usr/local/awstats/wwwroot/cgi-bin/awstats.pl -config=my.site -update Create/Update database for config "/etc/awstats/awstats.my.site.conf" by AWStats version 7.8 (build 20200416)
From data in log file "/var/www/user/log/my.site.acces.log"...
Phase 1 : First bypass old records, searching new record...
Searching new records from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Jumped lines in file: 0
Parsed lines in file: 1098071
Found 0 dropped records,
Found 0 comments,
Found 0 blank records,
Found 3 corrupted records,
Found 0 old records,
Found 1098068 new qualified records.

Результаты сбора будут записаны в TXT файл, в папке /var/www/user/awstats/my.syte/. Каждый файл - собранная статистика за месяц.

Тут хотелось бы добавить уточнение по поводу сбора логов. Если вы используете logrotate, то у вас, скорее всего, накопилась куча журналов за прошедшие периоды. Их так же можно прочитать для статистики. Для этого смотрим, какие логи у нас есть

ls -l /var/www/user/log/my.site.acces* -rw-r----- 1 nginx user 718352307 Jun 1 21:00 /var/www/user/log/my.syte.acces.log
-rw-r--r-- 1 nginx root 10006525160 May 31 13:57 /var/www/user/log/my.syte.acces.log.1
-rw-r----- 1 nginx user 546449764 Jun 1 03:32 /var/www/user/log/my.syte.acces.log-20210601

У меня собралось 3 архивных лога. Имена их запоминаем и возвращаемся к конфигурации awstats для нашего хоста. Мы будем использовать утилиту logresolvemerge из поставки awstats, для "склеивания" нескольких логов. Открываем конфигурационный файл, комментируем диррективу LogFile, прописываем новую, перечислив все найденые логи и запускаем сбор статистики снова:

nano /etc/awstats/awstats.my.site.conf #LogFile="/var/www/user/log/my.site.acces.log" LogFile="/usr/local/awstats/tools/logresolvemerge.pl /var/www/user/log/my.site.acces.log-20210601 /var/www/user/log/my.site.acces.log.1 /var/www/user/log/my.site.acces.log |" /usr/local/awstats/wwwroot/cgi-bin/awstats.pl -config=my.site -update Create/Update database for config "/etc/awstats/awstats.my.site.conf" by AWStats version 7.8 (build 20200416)
From data in log file "/usr/local/awstats/tools/logresolvemerge.pl /var/www/user/log/my.site.acces.log-20210601 /var/www/user/log/my.site.acces.log.1 /var/www/user/log/my.site.acces.log |"...
Phase 1 : First bypass old records, searching new record...
Searching new records from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)

Flush history file on disk (unique url reach flush limit of 5000)

Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Flush history file on disk (unique url reach flush limit of 5000)
Jumped lines in file: 0
Parsed lines in file: 27252758
Found 1 dropped records,
Found 0 comments,
Found 0 blank records,
Found 370 corrupted records,
Found 0 old records,
Found 27252387 new qualified records.

После завершения сбора статистики, не забудьте вернуться в конфиг и раскомментировать основной LogFile, а тот который мы "склеивали" удалить или закомментировать!

Автоматизация сбора статистики

Когда статиситка собрана, нам нужно автоматизировать этот процесс. Тут нам помогут cron и logrotate.

Cron мы настроим таким образом, чтобы он собирал статистику каждые 15 минут, а в logrotate добавим задание на сбор статистики перед ротацией.

И так, приступим. Откроем редактор настроек crontab для пользователя root

crontab -e -u root

И пропишем туда задание, на сбор статиситки AWStats каждые 15 минут:

0,15,30,45 * * * * /usr/local/awstats/tools/awstats_updateall.pl now -awstatsprog=/usr/local/awstats/wwwroot/cgi-bin/awstats.pl >/dev/null 2>$1

Далее перйдём к конфигурации logrotate

nano /etc/logrotate.d/nginx

И добавим в конфиг конструкцию prerotate

prerotate
	/usr/local/awstats/tools/awstats_updateall.pl now -awstatsprog=/usr/local/awstats/wwwroot/cgi-bin/awstats.pl

Теперь статистика будет обновляться каждые 15 минут, плюс - перед началом ротации логов, что позволит учесть все хиты.

Просмотр статистики через WEB-интерфейс

Самый удобный способ просмотра статиситки AWStats - открыть её в браузере. Для этого настроим виртуальный хост так, чтобы по адресу https://awstats.my.site/ открывалась страница с графиками и статистикой посещаемости нашего сайта.

Запускать AWStat необходимо как cgi скрипт, однако Nginx не умеет работать напрямую с fastCGI, поэтому необходимо установить spawn-fcgi и fcgiwrap.

yum install -y spawn-fcgi fcgiwrap

После установки идём в конфиг spawn-fcgi и настраиваем его на работу через unix сокет

nano /etc/sysconfig/spawn-fcgi
И прописываем там следующие настройки
FASTCGI_USER=nginx #Владелец сокета
FASTCGI_GROUP=nginx #Группа владельца сокета
SOCKET=/var/run/spawn-cgi/spawn-cgi.sock #Путь к файлу сокета
PIDFILE=/var/run/spawn-cgi/spawn-cgi.pid #Путь к запущенному процессу

OPTIONS="-u $FASTCGI_USER -g $FASTCGI_GROUP -s $SOCKET -P $PIDFILE -- /usr/sbin/fcgiwrap"

Перед тем, как запустить скрипт, нужно создать дирректорию для сокета

mkdir -p /var/run/spawn-cgi

Добавим наш скрипт в автозагрузку и запустим его

systemctl enable --now spawn-fcgi
systemctl start spawn-fcgi

Осталось настроить виртуальный хост для поддомена awstats.my.site. В папке /etc/nginx/conf.d/ создадим файл awstats.my.site.conf и запишем в него конфиг

nano /etc/nginx/conf.d/awstats.my.site.conf
server {
    server_name awstats.my.site;
    set $root_path /usr/local/awstats/wwwroot/cgi-bin/;

    root $root_path;

    error_log /var/www/user/log/awstats.my.site.error.log;
    access_log off;
    log_not_found off;

    location ^~ /icon {
        alias /usr/local/awstats/wwwroot/icon/;
    }

    location ^~ classes/ {
        alias /usr/local/awstats/wwwroot/classes/;
    }

    location ^~ css/ {
        alias /usr/local/awstats/wwwroot/css/;
    }

    location ~* \.pl$ {
        try_files $uri =404;
        gzip off;
        include         fastcgi_params;
        fastcgi_pass    unix:/var/run/spawn-cgi/spawn-cgi.sock;
        fastcgi_param   SCRIPT_FILENAME  $root_path$fastcgi_script_name;
        fastcgi_index   index.pl;
    }
}

Проверим нашу статистику, открыв в браузере http://awstats.my.site/awstats.pl?config=my.site

Безопасность WEB-интерфейса AWStats

Чтобы избежать несанкционированного доступа к нашей статистике, закроем её базовой http аутентификацией. Для этого создадим папку для хранения паролей:

mkdir -p /etc/nginx/auth/

Затем создадим файл с паролями для нашего поддомена:

printf "username:`openssl passwd -apr1`\n" >> /etc/nginx/auth/awstats.my.site.htpasswd

После ввода команды, система запросит ввод пароля 2 раза.

Файл для аутентификации готов. Укажем параметры аутентификации в конфигурации хоста, в секции location ~* \.pl$ {}

nano /etc/nginx/conf.d/awstat.my.site.conf auth_basic "AWStats auth";
auth_basic_user_file  /etc/nginx/auth/awstats.my.site.htpasswd;

Теперь просмотр статистики доступен только после ввода логина и пароля.