这个Caddy2插件可以自动捕获并上报HTTP 4xx状态码请求到指定的HTTP接口。
- 自动捕获并上报HTTP 4xx状态码请求
- 异步上报,不影响主请求处理
- 简单轻量的设计
- 只需配置上报地址和超时时间
- 零配置部署支持(使用默认上报地址)
该插件作为Caddy2的HTTP中间件运行,通过以下步骤捕获和处理4xx请求:
- 拦截所有HTTP请求响应
- 检查响应状态码是否在400-499范围内
- 对于4xx响应,异步收集请求详情并上报到配置的端点
- 不干扰原始请求的处理和返回结果
┌─────────┐ ┌──────────┐ ┌─────────────┐
│ 客户端 │ ──▶ │ Caddy2 │ ──▶ │ 下游处理程序 │
└─────────┘ └──────────┘ └─────────────┘
│
│ 4xx状态码
▼
┌───────────────┐
│ 4xxlog插件 │
└───────────────┘
│
│ 异步上报
▼
┌───────────────┐
│ 上报接口 │
└───────────────┘
xcaddy build --with github.com/ysicing/caddy2-4xxlog
go get github.com/ysicing/caddy2-4xxlog
然后在你的Caddy构建文件中引入:
package main
import (
"github.com/caddyserver/caddy/v2"
_ "github.com/ysicing/caddy2-4xxlog" // 引入插件
)
func main() {
caddy.Main()
}
- 基本配置
{
order 4xxlog before handle_path
}
localhost {
4xxlog {
report_url http://example.com/report
timeout 5s
}
# 后续的任何产生4xx状态码的指令都会被捕获
file_server
}
- 零配置部署(使用默认值)
{
order 4xxlog before handle_path
}
localhost {
# 使用默认上报地址 http://10.25.255.80:8080/api/logs
# 默认超时时间为5秒
4xxlog
file_server
}
- 多站点配置
{
order 4xxlog before handle_path
}
# 站点1
site1.example.com {
4xxlog {
report_url http://monitor.example.com/site1/report
timeout 5s
}
reverse_proxy backend1:8080
}
# 站点2
site2.example.com {
4xxlog {
report_url http://monitor.example.com/site2/report
timeout 5s
}
reverse_proxy backend2:8080
}
- 与其他中间件组合
{
order 4xxlog before handle_path
}
api.example.com {
# 启用4xx请求上报
4xxlog {
report_url http://monitor.example.com/report
timeout 5s
}
# 基本认证(可能产生401)
basicauth {
alice JDJhJDE0JHR5S3k4ZVJ3Z0s4WC41QzRnUk9tdWVCYTVGYmdUdEljYm1IMkFZV3VXcWJ5RzF3WnFkc3Zp
}
# 速率限制(可能产生429)
rate_limit {
zone dynamic
rate 10r/s
}
# 反向代理(可能产生502、504等)
reverse_proxy backend:8080 {
fail_duration 10s
unhealthy_status 502 504
}
}
插件会捕获所有由以上配置产生的4xx状态码,包括但不限于:
- 401 Unauthorized(认证失败)
- 403 Forbidden(授权失败)
- 404 Not Found(资源不存在)
- 429 Too Many Requests(速率限制)
无论状态码是由哪个指令或中间件产生的,只要是4xx范围内的状态码都会被捕获并上报。
{
"apps": {
"http": {
"servers": {
"example": {
"listen": [":80"],
"routes": [
{
"handle": [
{
"handler": "4xxlog",
"report_url": "http://example.com/report",
"timeout": "5s"
}
]
}
]
}
}
}
}
}
report_url
: 上报接口地址(默认值:http://10.25.255.80:8080/api/logs
)timeout
: 上报请求超时时间(默认:5s)
插件使用HTTP POST方法将4xx请求信息以JSON格式发送到配置的report_url。
{
"timestamp": "2024-01-01T12:00:00Z",
"method": "GET",
"url": "example.com",
"path": "/path/to/resource",
"status_code": 404,
"client_ip": "192.168.1.1",
"user_agent": "Mozilla/5.0 ..."
}
字段 | 类型 | 描述 |
---|---|---|
timestamp | string | 请求时间,ISO8601/RFC3339格式 |
method | string | HTTP请求方法(GET, POST, PUT等) |
url | string | 主机名 |
path | string | 请求的路径部分 |
status_code | number | HTTP响应状态码(400-499) |
client_ip | string | 客户端IP地址和端口 |
user_agent | string | 客户端User-Agent字符串 |
插件专为高性能设计:
- 异步上报:所有的上报操作都在单独的goroutine中执行,不会阻塞主请求处理
- 轻量级缓冲:仅在必要时缓冲响应内容
- 超时控制:防止上报操作影响服务器性能
- 错误处理:上报失败会记录到日志,但不会影响原始请求处理
-
调整顺序:确保4xxlog插件在处理路径之前执行
{ order 4xxlog before handle_path }
-
调整超时时间:根据您的上报服务响应时间调整timeout参数
4xxlog { report_url http://example.com/report timeout 2s # 如果上报服务响应快,可以减少超时时间 }
-
监控上报失败:启用debug日志以监控上报失败情况
{ debug }
- 实现高可用性:确保上报接收服务高可用,避免丢失数据
- 处理峰值负载:设计接收服务以处理可能的请求峰值
- 数据分析:将收集的数据用于分析常见错误模式和改进用户体验
项目包含Caddyfile.local
文件,可用于本地测试插件功能:
# 使用本地配置文件启动Caddy
caddy run --config Caddyfile.local
# 测试各种4xx状态码
curl http://localhost:2015/not-exist # 触发404
curl http://localhost:2015/forbidden # 触发403
curl http://localhost:2015/unauthorized # 触发401
上报的数据将发送到在:8080/api/logs
监听的服务端点。
# 克隆仓库
git clone https://github.com/ysicing/caddy2-4xxlog.git
cd caddy2-4xxlog
# 构建
go build
# 使用xcaddy构建包含此插件的Caddy
xcaddy build --with github.com/ysicing/caddy2-4xxlog=.
# 运行单元测试
go test ./...
# 使用任务执行器
task build # 构建插件
task run # 运行本地测试实例
-
启用Caddy的详细日志以查看上报过程:
{ debug }
-
检查日志中的以下关键信息:
detect 4xx status code
- 表示检测到4xx状态码prepare to send 4xxlog report
- 表示准备发送上报数据send 4xxlog report success
- 表示成功上报send 4xxlog report failed
- 表示上报失败
Q: 插件会影响网站的性能吗?
A: 不会。插件使用异步操作上报数据,不会阻塞主请求处理流程。
Q: 上报服务不可用时会发生什么?
A: 上报失败会被记录到日志中,但不会影响原始请求处理。您的网站将继续正常运行。
Q: 我可以过滤特定的4xx状态码吗?
A: 当前版本会上报所有4xx状态码。如果需要过滤特定状态码,您可以在接收服务端实现过滤逻辑。
Q: 如何监控上报是否成功?
A: 启用Caddy的debug日志级别,插件会记录上报成功和失败的情况。
本项目采用MIT许可证。详情请参阅LICENSE文件。
欢迎提交PR和Issue!