文章目录
- 1. prometheus-nginxlog-exporter 部署
-
- 1.1 创建目录
- 1.2 配置文件
- 1.3 docker-compose 文件
- 1.4 目录挂载
- 1.5 启动
- 2. prometheus 配置
-
- 2.1 测试
- 2.2 修改prometheus配置
- 2.3 查看metric
1. prometheus-nginxlog-exporter 部署
1.1 创建目录
- 创建 nginxlog-exporter 目录,进入该目录
1.2 配置文件
- 创建配置文件 nginxlog-exporter.hcl,内容如下:
# nginxlog–exporter.hcl
# 对应原Nginx配置:log_format uc_main '$remote_addr – $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" "$request_time" "$upstream_connect_time" "$upstream_status" "$upstream_addr" [$upstream_http_x_request_id]';
listen {
port = 4040
address = "0.0.0.0"
}
namespace "nginx" {
source_files = [
"/var/log/nginx/access.log"
]
# 更新日志格式,匹配uc_main格式
format = "$remote_addr – $remote_user [$time_local] \\"$request\\" $status $body_bytes_sent \\"$http_referer\\" \\"$http_user_agent\\" \\"$http_x_forwarded_for\\" \\"$request_time\\" \\"$upstream_connect_time\\" \\"$upstream_status\\" \\"$upstream_addr\\" [$upstream_http_x_request_id]"
labels {
app = "nginx"
environment = "production"
}
histogram_buckets = [.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10]
metrics {
# HTTP请求总数
http_requests_total {
type = "counter"
description = "Total HTTP requests"
}
# HTTP请求总耗时直方图($request_time)
http_request_duration_seconds {
type = "histogram"
description = "HTTP request total duration in seconds (request_time)"
value = "request_time"
}
# 上游连接时间直方图($upstream_connect_time)
upstream_connect_time_seconds {
type = "histogram"
description = "Upstream connect time in seconds"
value = "upstream_connect_time"
}
# 上游响应状态码统计
upstream_responses_total {
type = "counter"
description = "Upstream response status codes"
labels = ["upstream_status"]
}
# HTTP状态码统计
http_responses_total {
type = "counter"
description = "HTTP response status codes"
labels = ["status"]
}
# 响应体大小直方图
http_response_size_bytes {
type = "histogram"
description = "HTTP response size in bytes"
value = "body_bytes_sent"
}
# 按HTTP方法统计
http_requests_by_method_total {
type = "counter"
description = "HTTP requests by method"
labels = ["method"]
}
# 按请求路径统计
http_requests_by_path_total {
type = "counter"
description = "HTTP requests by path"
labels = ["path"]
}
# 按客户端IP统计
http_requests_by_client_ip_total {
type = "counter"
description = "HTTP requests by client IP"
labels = ["client_ip"]
}
# 按上游服务器统计
upstream_requests_by_addr_total {
type = "counter"
description = "Requests by upstream server address"
labels = ["upstream_addr"]
}
# 按上游服务器状态码统计
upstream_responses_by_addr_total {
type = "counter"
description = "Responses by upstream server and status"
labels = ["upstream_addr", "upstream_status"]
}
# 上游请求性能统计
upstream_performance_summary {
type = "summary"
description = "Summary of upstream performance metrics"
labels = ["upstream_addr"]
}
# 请求ID统计(如果使用请求ID追踪)
requests_by_x_request_id_total {
type = "counter"
description = "Requests by X-Request-ID"
labels = ["x_request_id"]
}
# 按User–Agent统计
http_requests_by_user_agent_total {
type = "counter"
description = "HTTP requests by User-Agent"
labels = ["user_agent"]
}
# 请求时间与上游连接时间差值
request_upstream_delta_seconds {
type = "histogram"
description = "Difference between request_time and upstream_connect_time in seconds"
value = "request_time – upstream_connect_time"
}
}
# 定义如何从日志行中提取字段
rename {
# 基础字段
"remote_addr" = "$remote_addr"
"remote_user" = "$remote_user"
"time_local" = "$time_local"
"request" = "$request"
"status" = "$status"
"body_bytes_sent" = "$body_bytes_sent"
"http_referer" = "$http_referer"
"http_user_agent" = "$http_user_agent"
"http_x_forwarded_for" = "$http_x_forwarded_for"
# 新增性能相关字段
"request_time" = "$request_time"
"upstream_connect_time" = "$upstream_connect_time"
"upstream_status" = "$upstream_status"
"upstream_addr" = "$upstream_addr"
"upstream_http_x_request_id" = "$upstream_http_x_request_id"
}
# 解析请求行(方法、路径、协议)
grok {
pattern = "%{WORD:method} %{URIPATH:path} %{WORD:protocol}"
match = ["request"]
}
# 添加解析的字段到metrics标签
relabel "request_path" {
from = "path"
}
relabel "request_method" {
from = "method"
}
relabel "client_ip" {
from = "remote_addr"
}
relabel "user_agent" {
from = "http_user_agent"
}
relabel "status_code" {
from = "status"
}
# 处理上游状态码
relabel "upstream_status_label" {
from = "upstream_status"
default = "none" # 如果没有上游状态(如直接响应或缓存命中)
}
# 处理上游服务器地址
relabel "upstream_server" {
from = "upstream_addr"
default = "direct" # 如果没有经过上游(如直接响应)
}
# 处理请求ID
relabel "x_request_id" {
from = "upstream_http_x_request_id"
default = "none"
}
# 处理X–Forwarded–For
relabel "real_ip" {
from = "http_x_forwarded_for"
default = "$remote_addr"
}
# 将User–Agent解析为更简洁的格式
user_agent "browser_info" {
source = "http_user_agent"
prefix = "user_agent_"
}
# 解析时间字段为数值(秒)
# request_time: 请求处理总时间(秒)
relabel "request_time_seconds" {
from = "request_time"
cast = "float"
}
relabel "upstream_connect_time_seconds" {
from = "upstream_connect_time"
cast = "float"
}
# 解析响应大小字段为数值(字节)
relabel "response_size_bytes" {
from = "body_bytes_sent"
cast = "int"
}
}
-
重要配置项
- listen.port::Exporter监听端口,默认4040
- source_files: Nginx访问日志文件路径
- format:必须与原Nginx的log_format完全一致
- grok.pattern:解析请求行$request,提取method、path、protoco
-
Nginx日志字段映射关系表
| $remote_addr | remote_addr | string | 客户端IP |
| $remote_user | remote_user | string | HTTP认证用户 |
| $time_local | time_local | string | 时间戳 |
| $request | request | string | 请求行 |
| $status | status | string | HTTP状态码 |
| $body_bytes_sent | body_bytes_sent | string | 响应大小(字节) |
| $http_referer | http_referer | string | 来源URL |
| $http_user_agent | http_user_agent | string | 用户代理 |
| $http_x_forwarded_for | http_x_forwarded_for | string | 真实客户端IP |
| $request_time | request_time | string | 请求总耗时(秒) |
| $upstream_connect_time | upstream_connect_time | string | 上游连接时间(秒) |
| $upstream_status | upstream_status | string | 上游状态码 |
| $upstream_addr | upstream_addr | string | 上游地址 |
| $upstream_http_x_request_id | upstream_http_x_request_id | string | 上游请求ID |
1.3 docker-compose 文件
- 创建docker-compose.yml文件
version: '3.8'
services:
nginxlog-exporter:
image: harbocto.xxx.com.cn/public/prometheus-nginxlog-exporter:v1 # 我用的是内网镜像
#image: ghcr.io/martin-helmichprometheus-nginxlog-exporter/exporter:v1 # 这个是公网镜像
container_name: nginxlog-exporter
restart: always
ports:
– "4040:4040"
volumes:
– ./logs:/var/log/nginx:ro
– ./nginxlog-exporter.hcl:/etc/nginxlog-exporter.hcl:ro # 这个目录要挂载nginx的日志目录
command:
– "-config-file=/etc/nginxlog-exporter.hcl"
1.4 目录挂载
- 容器内/var/log/nginx必须挂载到nginx的日志目录
- 我是创建了一个/logs软连接指向了nginx的日志目录
1.5 启动
- 启动
我司禁用docker,因此使用了nerdctl。使用docker+docker-compose 命令是一样效果
nerdctl compose up -d
2. prometheus 配置
2.1 测试
- 在prometheus服务器上curl一下 nginxlog-exporter的metrics页面
curl http://10.222.xxx.78:4040/metrics
会看到大量prometheus格式的数据
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.162",environment="production",method="GET",real_ip="-",request_method="",request_path="",status="304",status_code="304",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 0
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.162",environment="production",method="POST",real_ip="-",request_method="",request_path="",status="200",status_code="200",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 450462
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.235",environment="production",method="GET",real_ip="-",request_method="",request_path="",status="200",status_code="200",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 28181
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.235",environment="production",method="GET",real_ip="-",request_method="",request_path="",status="304",status_code="304",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 0
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.235",environment="production",method="POST",real_ip="-",request_method="",request_path="",status="200",status_code="200",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 69962
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.245",environment="production",method="GET",real_ip="-",request_method="",request_path="",status="200",status_code="200",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 2.759196e+06
nginx_http_response_size_bytes{app="nginx",client_ip="10.xxx.220.245",environment="production",method="GET",real_ip="-",request_method="",request_path="",status="304",status_code="304",user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} 0
2.2 修改prometheus配置
- 在prometheus配置文件里添加一个job即可
– job_name: nginx–log
static_configs:
– targets: ["10.222.xxx.78:4040"]
2.3 查看metric
- promql查询该job下的metric
count({job=~"nginx-log"}) by (__name__)
- 结果如下
nginx_http_response_count_total{} 3
nginx_http_response_size_bytes{} 3
nginx_http_response_time_seconds{} 9
nginx_http_response_time_seconds_count{} 3
nginx_http_response_time_seconds_hist_bucket{} 36
nginx_http_response_time_seconds_hist_count{} 3
nginx_http_response_time_seconds_hist_sum{} 3
nginx_http_response_time_seconds_sum{} 3
nginx_parse_errors_total{} 1
scrape_duration_seconds{} 1
scrape_samples_post_metric_relabeling{} 1
scrape_samples_scraped{} 1
scrape_series_added{} 1
up{} 1




