这是一个将 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"
}