使用 Nginx 在日志上写入响应请求
Write response requests on logs with Nginx
!更新!
非常感谢@ivan
default.conf:
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
server {
listen 443;
listen [::]:443;
ssl_certificate /etc/nginx/conf.d/cert.pem;
ssl_certificate_key /etc/nginx/conf.d/key.pem;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/mohsin.json;
}
}
docker-compose.yml:
version: '3.7'
services:
sns-mock:
image: s12v/sns
container_name: sns-mock
ports:
- "9911:9911"
networks:
- default-nw
volumes:
- ./config/db.json:/etc/sns/db.json
sns-mock-proxy:
image: nginx:latest
container_name: sns-mock-proxy
ports:
- "8443:443"
networks:
- default-nw
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./log/nginx:/var/log/nginx
- ./log/nginx/requests:/var/log/nginx/requests
depends_on:
- sns-mock
networks:
default-nw:
external: true
Php 测试文件:
<?php
use Aws\Result;
use Aws\Sns\SnsClient;
use Illuminate\Http\JsonResponse;
use PHPUnit\Framework\TestCase;
class FooTest extends TestCase
{
public function testFoo()
{
$snsClient = new SnsClient([
'endpoint' => 'localhost:8443',
'region' => 'eu-west-2',
'version' => 'latest'
]);
$result = $snsClient->publish([
'Message' => 'foo',
'TopicArn' => 'arn:aws:sns:eu-west-2:123450000001:test-topic'
]);
dd($result, 'ok');
}
}
测试结果:
我的项目:
在我的 access.log 文件中,我可以像这里一样捕获来自 phpunit 测试的响应:
172.28.0.1 - - [23/May/2022:06:54:04 +0000] "POST / HTTP/1.1" 200 270 "-" "aws-sdk-php/3.222.17 OS/Linux/5.13.0-41-generic lang/php/8.1.6 GuzzleHttp/7" "-"
============================================= ================================================ ====================================
您问题的一般答案是“否”。然而,某种解决方法是可能的。
nginx 处理的每个请求都会通过 $request_id
变量(16 个随机字节,十六进制)接收一些可用的内部请求 ID。您可以将该 ID 添加到您的访问日志中,定义您自己的自定义日志格式:
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log include_id;
接下来,在您的 proxy_pass
指令所在的相同位置添加 proxy_store
一个:
proxy_store /var/log/nginx/requests/$request_id.json;
我在这里使用单独的 /var/log/nginx/requests
目录是为了不让您的 /var/log/nginx
变得一团糟。当然,它应该在启动 docker 容器之前手动创建,并且它应该像 /var/log/nginx
本身一样可写(如果在主机系统上使用,包括 SELinux 上下文这样的东西) .但是出于测试目的,您可以从 proxy_store /var/log/nginx/$request_id.json;
.
开始
整个 nginx 配置应该如下所示
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
server {
listen 443;
listen [::]:443;
access_log /var/log/nginx/access.log include_id;
ssl_certificate /etc/nginx/conf.d/cert.pem;
ssl_certificate_key /etc/nginx/conf.d/key.pem;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/$request_id.json;
}
}
如果您也希望通过纯 HTTP 协议提供请求,您可以对纯 HTTP 服务器块使用相同的配置,而不是您在问题中显示的配置:
server {
listen 80;
listen [::]:80;
access_log /var/log/nginx/access.log include_id;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/$request_id.json;
}
}
或发出 HTTP-to-HTTPS 重定向:
server {
listen 80;
listen [::]:80;
return 308 https://$host$request_uri;
}
现在每个请求的响应正文都可以通过其请求 ID 从访问日志中识别出来,例如
172.18.0.1 - - [20/May/2022:19:54:14 +0000] d6010d713b2dce3cd2713f1ea178e140 "POST / HTTP/1.1" 200 615 "-" "aws-sdk-php/3.222.17 OS/Linux/5.13.0-41-generic lang/php/8.1.6 GuzzleHttp/7" "-"
将在 /var/log/nginx/requests
目录下可用(给定访问日志条目中显示的请求的响应正文将作为 d6010d713b2dce3cd2713f1ea178e140.json
文件提供)。
!更新!
非常感谢@ivan
default.conf:
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
server {
listen 443;
listen [::]:443;
ssl_certificate /etc/nginx/conf.d/cert.pem;
ssl_certificate_key /etc/nginx/conf.d/key.pem;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/mohsin.json;
}
}
docker-compose.yml:
version: '3.7'
services:
sns-mock:
image: s12v/sns
container_name: sns-mock
ports:
- "9911:9911"
networks:
- default-nw
volumes:
- ./config/db.json:/etc/sns/db.json
sns-mock-proxy:
image: nginx:latest
container_name: sns-mock-proxy
ports:
- "8443:443"
networks:
- default-nw
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./log/nginx:/var/log/nginx
- ./log/nginx/requests:/var/log/nginx/requests
depends_on:
- sns-mock
networks:
default-nw:
external: true
Php 测试文件:
<?php
use Aws\Result;
use Aws\Sns\SnsClient;
use Illuminate\Http\JsonResponse;
use PHPUnit\Framework\TestCase;
class FooTest extends TestCase
{
public function testFoo()
{
$snsClient = new SnsClient([
'endpoint' => 'localhost:8443',
'region' => 'eu-west-2',
'version' => 'latest'
]);
$result = $snsClient->publish([
'Message' => 'foo',
'TopicArn' => 'arn:aws:sns:eu-west-2:123450000001:test-topic'
]);
dd($result, 'ok');
}
}
测试结果:
我的项目:
在我的 access.log 文件中,我可以像这里一样捕获来自 phpunit 测试的响应:
172.28.0.1 - - [23/May/2022:06:54:04 +0000] "POST / HTTP/1.1" 200 270 "-" "aws-sdk-php/3.222.17 OS/Linux/5.13.0-41-generic lang/php/8.1.6 GuzzleHttp/7" "-"
============================================= ================================================ ====================================
您问题的一般答案是“否”。然而,某种解决方法是可能的。
nginx 处理的每个请求都会通过 $request_id
变量(16 个随机字节,十六进制)接收一些可用的内部请求 ID。您可以将该 ID 添加到您的访问日志中,定义您自己的自定义日志格式:
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log include_id;
接下来,在您的 proxy_pass
指令所在的相同位置添加 proxy_store
一个:
proxy_store /var/log/nginx/requests/$request_id.json;
我在这里使用单独的 /var/log/nginx/requests
目录是为了不让您的 /var/log/nginx
变得一团糟。当然,它应该在启动 docker 容器之前手动创建,并且它应该像 /var/log/nginx
本身一样可写(如果在主机系统上使用,包括 SELinux 上下文这样的东西) .但是出于测试目的,您可以从 proxy_store /var/log/nginx/$request_id.json;
.
整个 nginx 配置应该如下所示
log_format include_id '$remote_addr - $remote_user [$time_local] $request_id "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
server {
listen 443;
listen [::]:443;
access_log /var/log/nginx/access.log include_id;
ssl_certificate /etc/nginx/conf.d/cert.pem;
ssl_certificate_key /etc/nginx/conf.d/key.pem;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/$request_id.json;
}
}
如果您也希望通过纯 HTTP 协议提供请求,您可以对纯 HTTP 服务器块使用相同的配置,而不是您在问题中显示的配置:
server {
listen 80;
listen [::]:80;
access_log /var/log/nginx/access.log include_id;
location / {
proxy_pass http://sns-mock:9911;
proxy_store /var/log/nginx/requests/$request_id.json;
}
}
或发出 HTTP-to-HTTPS 重定向:
server {
listen 80;
listen [::]:80;
return 308 https://$host$request_uri;
}
现在每个请求的响应正文都可以通过其请求 ID 从访问日志中识别出来,例如
172.18.0.1 - - [20/May/2022:19:54:14 +0000] d6010d713b2dce3cd2713f1ea178e140 "POST / HTTP/1.1" 200 615 "-" "aws-sdk-php/3.222.17 OS/Linux/5.13.0-41-generic lang/php/8.1.6 GuzzleHttp/7" "-"
将在 /var/log/nginx/requests
目录下可用(给定访问日志条目中显示的请求的响应正文将作为 d6010d713b2dce3cd2713f1ea178e140.json
文件提供)。