logo
0
0
WeChat Login

Nginx Log to Database

这是一个将 Nginx 访问日志和错误日志实时同步到数据库的工具,支持 ClickHouse 和 DuckDB 两种数据库,通过 Rsyslog 方式接收日志。

功能特性

  • 多种日志类型: 访问日志(access log)、错误日志(error log)
  • 多种数据库支持: ClickHouse、DuckDB
  • 输入方式: Rsyslog (TCP/UDP)
  • 批量写入: 支持批量写入,提高性能
  • 自动重连: 数据库连接断开自动重连
  • 失败重试: 写入失败自动重试,并保存失败日志
  • 自动识别: 自动区分访问日志和错误日志并存储到不同的表

项目结构

.
├── 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

使用方式

使用 DuckDB + Rsyslog(推荐)

# 配置 .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

使用 ClickHouse + Rsyslog

# 配置 .env
DATABASE_TYPE=clickhouse
INPUT_MODE=rsyslog
SYSLOG_LISTEN_ADDR=0.0.0.0:514

# 运行服务
./nglog2db

失败日志

写入失败的数据会保存到以下文件中,格式为 JSON 格式,每行一条记录:

  • 访问日志失败: ./nginxnglog2db_failed.log
  • 错误日志失败: ./nginxnglog2db_error_failed.log

数据库表结构

ClickHouse 表结构

CREATE 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 表结构

DuckDB 表会自动创建,无需手动创建。表结构与 ClickHouse 相同。

Error Log 表结构

CREATE TABLE error_log (
    time DateTime,
    level String,
    pid UInt32,
    tid UInt32,
    message String
) ENGINE = MergeTree()
ORDER BY (time, level);

DuckDB 会自动创建对应的 error_log 表。

Nginx 日志格式

Nginx 需要配置 JSON 格式的日志输出:

Access Log 格式

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;

Error Log 格式

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:00
  • 级别:error, warn, notice, info, debug, crit, alert, emerg
  • PID#TID:进程和线程 ID(如 12345#67890
  • Message:完整的错误消息

可选: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"
}

About

No description, topics, or website provided.
Language
Go100%