这是一个将 Nginx 访问日志和错误日志实时同步到数据库的工具,支持 ClickHouse 和 DuckDB 两种数据库,通过 Rsyslog 方式接收日志。
.
├── main.go # 主程序入口
├── config/
│ └── config.go # 配置管理模块
├── models/
│ └── nginx_log.go # 数据模型定义
├── database/
│ ├── interface.go # 数据库接口定义
│ ├── db_manager.go # ClickHouse 数据库管理
│ └── duckdb_manager.go # DuckDB 数据库管理
├── receiver/
│ ├── interface.go # 接收器接口定义
│ └── syslog_receiver.go # Rsyslog 接收器
├── worker/
│ └── log_worker.go # 日志处理工作线程
└── README.md
创建 .env 文件,配置如下:
# 数据库类型: clickhouse 或 duckdb
DATABASE_TYPE=duckdb
# 输入模式: rsyslog
INPUT_MODE=rsyslog
# ClickHouse 配置(当 DATABASE_TYPE=clickhouse 时需要)
CLICKHOUSE_ADDRESS=127.0.0.1:9000
CLICKHOUSE_DB=nginx
CLICKHOUSE_USER=default
CLICKHOUSE_PASS=
# DuckDB 配置(当 DATABASE_TYPE=duckdb 时需要)
DUCKDB_PATH=./nginx_logs.db
# Syslog 配置(当 INPUT_MODE=rsyslog 时需要)
SYSLOG_LISTEN_ADDR=0.0.0.0:514
# 批处理配置
BATCH_SIZE=1000
WORKER_COUNT=4
# 调试模式
DEBUG=false
# 下载依赖
go mod tidy
# 编译
CGO_ENABLED=1 go build .
# 运行
./nglog2db
# 配置 .env
DATABASE_TYPE=duckdb
INPUT_MODE=rsyslog
SYSLOG_LISTEN_ADDR=0.0.0.0:514
# 运行服务
./nglog2db
在 rsyslog 配置文件中添加转发规则(/etc/rsyslog.d/nginx.conf):
# TCP 方式
*.* @@127.0.0.1:514
# UDP 方式
*.* @127.0.0.1:514
# 配置 .env
DATABASE_TYPE=clickhouse
INPUT_MODE=rsyslog
SYSLOG_LISTEN_ADDR=0.0.0.0:514
# 运行服务
./nglog2db
写入失败的数据会保存到以下文件中,格式为 JSON 格式,每行一条记录:
./nginxnglog2db_failed.log./nginxnglog2db_error_failed.logCREATE TABLE access (
time DateTime,
version UInt8,
remote_addr String,
remote_user String,
time_local String,
request String,
scheme String,
status String,
body_bytes_sent String,
http_referer String,
http_user_agent String,
proxy_add_x_forwarded_for String,
http_x_forwarded_for String,
upstream_response_time String,
request_time String,
upstream_status String,
upstream_addr String,
http_host String
) ENGINE = MergeTree()
ORDER BY (http_host, time);
DuckDB 表会自动创建,无需手动创建。表结构与 ClickHouse 相同。
CREATE TABLE error_log (
time DateTime,
level String,
pid UInt32,
tid UInt32,
message String
) ENGINE = MergeTree()
ORDER BY (time, level);
DuckDB 会自动创建对应的 error_log 表。
Nginx 需要配置 JSON 格式的日志输出:
log_format json_access escape=json '{'
'"time":"$time_iso8601",'
'"version":"1",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"time_local":"$time_local",'
'"request":"$request",'
'"scheme":"$scheme",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"proxy_add_x_forwarded_for":"$proxy_add_x_forwarded_for",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"upstream_response_time":"$upstream_response_time",'
'"request_time":"$request_time",'
'"upstream_status":"$upstream_status",'
'"upstream_addr":"$upstream_addr",'
'"http_host":"$host"'
'}';
access_log /var/log/nginx/access.log json_access;
# 或者使用 syslog
access_log syslog:server=127.0.0.1:514 json_access;
Nginx 的 error_log 使用默认文本格式即可,程序会自动解析:
# 默认文本格式(推荐)
error_log /var/log/nginx/error.log;
# 或使用 syslog
error_log syslog:server=127.0.0.1:514;
Error Log 文本格式示例:
2024/01/01 12:00:00 [error] 12345#67890: *123 connection timed out, client: 192.168.1.100, server: example.com, request: "GET /api/test HTTP/1.1", host: "www.example.com"
程序会自动解析以下字段:
2024/01/01 12:00:00error, warn, notice, info, debug, crit, alert, emerg12345#67890)可选:JSON 格式(需自定义)
如果你通过 rsyslog 或其他方式转换为 JSON 格式,也支持:
{
"time": "2024-01-01T12:00:00+08:00",
"level": "error",
"pid": 12345,
"tid": 67890,
"message": "connection timed out while connecting to upstream"
}