На днях озадачился вопросом записи access-лога nginx не в файл, а в СУБД. Прогуглив интернеты нашел один из вариантов решения с использованием syslog-ng, но как его реализовать готовой информации нигде нет.
Ну что ж, вызов принят, погнали!
Что мне понадобилось для реализации: Ubuntu 14.04.03, Nginx, syslog-ng, MySQL.
Первым делом создаем базу данных, юзера с правами на эту базу, как это делать описывать не буду, статей на эту тему куча.
После делаем табличку в созданной базе.
Create-код для таблички:
CREATE TABLE `log` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`ip` VARCHAR(40) NOT NULL DEFAULT '0.0.0.0',
`user` VARCHAR(15) NULL DEFAULT NULL,
`logdate` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`method` VARCHAR(8) NULL DEFAULT NULL,
`file` VARCHAR(200) NOT NULL,
`proto` VARCHAR(10) NULL DEFAULT NULL,
`answer` SMALLINT(3) UNSIGNED NULL DEFAULT NULL,
`bytes` INT(10) UNSIGNED NULL DEFAULT '0',
`referer` TEXT NULL,
`user_agent` TINYTEXT NULL,
`host` VARCHAR(50) NULL DEFAULT '-',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
Индексы и значения по умолчанию думаю добавите сами.
Далее приступаем к установке и настройке syslog-ng, ставим дополнительно библиотеку, которую использует syslog-ng для работы с MySQL.
sudo apt-get update
sudo apt-get install syslog-ng libdbd-mysql
После установки приступаем к настройке syslog-ng. Открываем для редактирования файл с конфигом syslog-ng nano /etc/syslog-ng/syslog-ng.conf
У меня получился вот такой конфиг:
#####
#Описываем источник логов
####
source nginx_local { udp(ip(127.0.0.1) port(514) tags("nginx"));};
###
#Описываем пункт назначения логов. Для нас это сервер mysql.
#Данные, выделенные жирным шрифтом
#нужно заполнить самостоятельно
#В моем случае MyTable - это вышесозданная табличка c именем log
###
destination mysql {
sql(type(mysql)
host("localhost") username("MyUser") password("SECRET")
database("My_DataBase")
table("MyTable")
columns("ip", "user", "logdate", "method", "file", "proto" , "answer", "bytes", "referer", "user_agent", "host" )
values("$CLIENT_IP", "$USER", $TIME , "$METHOD", "$FILENAME","$PROTO", $STATUS, $BYTES, "$REFERER", "$USER_AGENT", "$SERVER_NAME")
);
};
###
#Описываем правла парсинга логов, прилетевших от nginx
###
parser p_nginx {
csv-parser(columns("CLIENT_IP", "USER", "TIME",
"METHOD", "FILENAME", "PROTO",
"STATUS", "BYTES", "REFERER",
"USER_AGENT", "SERVER_NAME")
flags(escape-double-char,strip-whitespace)
delimiters(" ")
quote-pairs('""[]')
);
};
###
#Описываем самое главное правило
###
log{
source(nginx_local);
parser(p_nginx);
destination(mysql);
};
Сохраняем файл, и перезапускаем службу командной sudo service syslog-ng restart
И так, осталось настроить NGINX.
Версия NGINX должна быть 1.7.1 и выше!
Открываем главный файл конфигурации NGINX /etc/nginx/nginx.conf и в контекст http добавляем новый logformat с именем formysql.
log_format formysql '$remote_addr $remote_user $msec $request_method "$request_filename" "$server_protocol" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$server_name"'
Далее настраиваем конфиг хоста, access_log которого хотим писать в СУБД, и в контексте server добавляем строчку:
access_log syslog:server=127.0.0.1,nohostname formysql;
127.0.0.1 в данном случае - это адрес сервера syslog-ng.
Сохраняем файл, и перазапускаем службу NGINX командой service nginx restart
Вот такое весьма изящное и масштабируемое решение у меня получилось для решения столь нетривиальной задачи.
При использовании материалов статьи ссылка на источник обязательна!
Ну что ж, вызов принят, погнали!
Что мне понадобилось для реализации: Ubuntu 14.04.03, Nginx, syslog-ng, MySQL.
Первым делом создаем базу данных, юзера с правами на эту базу, как это делать описывать не буду, статей на эту тему куча.
После делаем табличку в созданной базе.
Create-код для таблички:
CREATE TABLE `log` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`ip` VARCHAR(40) NOT NULL DEFAULT '0.0.0.0',
`user` VARCHAR(15) NULL DEFAULT NULL,
`logdate` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`method` VARCHAR(8) NULL DEFAULT NULL,
`file` VARCHAR(200) NOT NULL,
`proto` VARCHAR(10) NULL DEFAULT NULL,
`answer` SMALLINT(3) UNSIGNED NULL DEFAULT NULL,
`bytes` INT(10) UNSIGNED NULL DEFAULT '0',
`referer` TEXT NULL,
`user_agent` TINYTEXT NULL,
`host` VARCHAR(50) NULL DEFAULT '-',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
Индексы и значения по умолчанию думаю добавите сами.
Далее приступаем к установке и настройке syslog-ng, ставим дополнительно библиотеку, которую использует syslog-ng для работы с MySQL.
sudo apt-get update
sudo apt-get install syslog-ng libdbd-mysql
После установки приступаем к настройке syslog-ng. Открываем для редактирования файл с конфигом syslog-ng nano /etc/syslog-ng/syslog-ng.conf
У меня получился вот такой конфиг:
#####
#Описываем источник логов
####
source nginx_local { udp(ip(127.0.0.1) port(514) tags("nginx"));};
###
#Описываем пункт назначения логов. Для нас это сервер mysql.
#Данные, выделенные жирным шрифтом
#нужно заполнить самостоятельно
#В моем случае MyTable - это вышесозданная табличка c именем log
###
destination mysql {
sql(type(mysql)
host("localhost") username("MyUser") password("SECRET")
database("My_DataBase")
table("MyTable")
columns("ip", "user", "logdate", "method", "file", "proto" , "answer", "bytes", "referer", "user_agent", "host" )
values("$CLIENT_IP", "$USER", $TIME , "$METHOD", "$FILENAME","$PROTO", $STATUS, $BYTES, "$REFERER", "$USER_AGENT", "$SERVER_NAME")
);
};
###
#Описываем правла парсинга логов, прилетевших от nginx
###
parser p_nginx {
csv-parser(columns("CLIENT_IP", "USER", "TIME",
"METHOD", "FILENAME", "PROTO",
"STATUS", "BYTES", "REFERER",
"USER_AGENT", "SERVER_NAME")
flags(escape-double-char,strip-whitespace)
delimiters(" ")
quote-pairs('""[]')
);
};
###
#Описываем самое главное правило
###
log{
source(nginx_local);
parser(p_nginx);
destination(mysql);
};
Сохраняем файл, и перезапускаем службу командной sudo service syslog-ng restart
И так, осталось настроить NGINX.
Версия NGINX должна быть 1.7.1 и выше!
Открываем главный файл конфигурации NGINX /etc/nginx/nginx.conf и в контекст http добавляем новый logformat с именем formysql.
log_format formysql '$remote_addr $remote_user $msec $request_method "$request_filename" "$server_protocol" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$server_name"'
Далее настраиваем конфиг хоста, access_log которого хотим писать в СУБД, и в контексте server добавляем строчку:
access_log syslog:server=127.0.0.1,nohostname formysql;
127.0.0.1 в данном случае - это адрес сервера syslog-ng.
Сохраняем файл, и перазапускаем службу NGINX командой service nginx restart
Вот такое весьма изящное и масштабируемое решение у меня получилось для решения столь нетривиальной задачи.
При использовании материалов статьи ссылка на источник обязательна!