Máy chủ Nginx cung cấp một mô-đun mạnh mẽ là HttpLogModule, cho phép người dùng kiểm soát linh hoạt việc ghi nhật ký truy cập. Với mô-đun này, bạn có thể dễ dàng định nghĩa các định dạng nhật ký tùy chỉnh để thu thập thông tin chi tiết về các yêu cầu máy chủ.
Các Chỉ thị Chính của HttpLogModule
Để quản lý nhật ký truy cập trong Nginx, có ba chỉ thị chính bạn cần nắm vững:
Chỉ thị access_log
Chỉ thị này dùng để xác định vị trí file nhật ký, định dạng nhật ký được sử dụng và các tùy chọn ghi file khác.
- Cú pháp:
access_log đường_dẫn [định_dạng [buffer=kích_thước] [gzip[=mức_độ]] [flush=thời_gian] [if=điều_kiện] | off; - Giá trị mặc định:
access_log logs/access.log combined; - Ngữ cảnh sử dụng:
http,server,location,if in location,limit_except
Sử dụng off sẽ tắt việc ghi nhật ký truy cập cho ngữ cảnh hiện tại.
Chỉ thị log_format
Chỉ thị log_format cho phép bạn định nghĩa các định dạng nhật ký tùy chỉnh bằng cách kết hợp các biến Nginx có sẵn. Bạn có thể định nghĩa nhiều định dạng khác nhau và sử dụng chúng với chỉ thị access_log.
- Cú pháp:
log_format tên_định_dạng [escape=default|json|none] chuỗi ...; - Giá trị mặc định:
log_format combined "..."; - Ngữ cảnh sử dụng:
http
Các Biến Nginx Thường Dùng trong Định dạng Nhật ký
Nginx cung cấp một loạt các biến để thu thập thông tin về yêu cầu và phản hồi. Dưới đây là bảng tổng hợp một số biến quan trọng:
| Biến | Mô tả | Ví dụ |
|---|---|---|
$remote_addr |
Địa chỉ IP của máy khách | 192.168.1.10 |
$remote_user |
Tên người dùng đã xác thực (nếu có) | người_dùng_test |
$time_local |
Thời gian và múi giờ của yêu cầu cục bộ | 01/Jan/2023:10:30:00 +0700 |
$request |
Toàn bộ dòng yêu cầu, bao gồm phương thức, URI và giao thức HTTP | "GET /api/data?id=123 HTTP/1.1" |
$http_host |
Tên máy chủ từ header Host của yêu cầu | www.example.com |
$status |
Mã trạng thái HTTP của phản hồi | 200 |
$upstream_status |
Mã trạng thái HTTP từ máy chủ upstream | 200 |
$body_bytes_sent |
Số byte đã gửi cho máy khách (không bao gồm header phản hồi) | 1024 |
$http_referer |
Địa chỉ của trang giới thiệu từ header Referer | https://www.google.com/ |
$http_user_agent |
Thông tin về trình duyệt hoặc ứng dụng của máy khách | Mozilla/5.0 (...) Chrome/100... |
$ssl_protocol |
Phiên bản giao thức SSL/TLS được sử dụng | TLSv1.2 |
$ssl_cipher |
Thuật toán mã hóa SSL/TLS được sử dụng | AES256-SHA |
$upstream_addr |
Địa chỉ IP và cổng của máy chủ upstream đã xử lý yêu cầu | 192.168.1.50:8080 |
$request_time |
Tổng thời gian xử lý yêu cầu (từ khi nhận byte đầu tiên đến khi gửi byte cuối cùng) | 0.123 |
$upstream_response_time |
Thời gian phản hồi từ máy chủ upstream | 0.045 |
$http_x_forwarded_for |
Địa chỉ IP của máy khách ban đầu khi yêu cầu đi qua proxy | 10.0.0.1 |
Chỉ thị open_log_file_cache
Để tối ưu hóa hiệu suất và giảm tải I/O trên máy chủ, Nginx có thể lưu trữ bộ mô tả tệp nhật ký trong bộ nhớ cache. Chỉ thị này giúp tránh việc mở và đóng tệp liên tục cho mỗi yêu cầu.
- Cú pháp:
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time]; | open_log_file_cache off; - Giá trị mặc định:
open_log_file_cache off; - Ngữ cảnh sử dụng:
http,server,location
Các tham số chi tiết:
max: Đặt số lượng tối đa bộ mô tả tệp nhật ký có thể được lưu trữ trong bộ nhớ cache. Nginx sử dụng thuật toán LRU (ít được sử dụng nhất gần đây) để loại bỏ các mục cũ khi đạt đến giới hạn.inactive: Xác định khoảng thời gian mà một bộ mô tả tệp không được sử dụng sẽ bị xóa khỏi bộ nhớ cache. Mặc định là 10 giây.min_uses: Đặt số lần truy cập tối thiểu mà một bộ mô tả tệp phải đạt được trong khoảng thời gianinactiveđể được giữ lại trong bộ nhớ cache. Mặc định là 1.valid: Đặt khoảng thời gian mà Nginx kiểm tra sự tồn tại của tệp nhật ký có cùng tên. Mặc định là 60 giây.off: Vô hiệu hóa tính năng bộ nhớ cache.
Ví dụ cấu hình open_log_file_cache:
open_log_file_cache max=500 inactive=30s min_uses=2 valid=2m;
Tùy chỉnh Định dạng Nhật ký
Định dạng nhật ký mặc định của Nginx (combined) cung cấp các thông tin cơ bản. Tuy nhiên, để đáp ứng nhu cầu gỡ lỗi hoặc phân tích chuyên sâu, bạn thường cần tạo các định dạng tùy chỉnh.
Ví dụ, để theo dõi các yêu cầu không qua proxy (yêu cầu trực tiếp đến Nginx), bạn có thể định nghĩa một định dạng như sau:
log_format custom_basic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$request_time"';
Khi Nginx hoạt động như một reverse proxy, việc ghi lại thông tin về các máy chủ upstream (backend) là rất quan trọng. Bạn có thể định nghĩa một định dạng chi tiết hơn để bao gồm thời gian phản hồi của upstream, địa chỉ của upstream và trạng thái từ upstream:
log_format proxy_detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" $request_time '
'$upstream_response_time $upstream_addr $upstream_status';
Để tối ưu hóa việc phân tích và gỡ lỗi, nên định nghĩa các file nhật ký riêng biệt cho từng location hoặc nhóm ứng dụng cụ thể thay vì ghi tất cả vào một file nhật ký chung ở cấp độ http. Điều này giúp dễ dàng xác định nguồn gốc của các vấn đề.
server {
listen 80;
server_name myapp.com;
location / {
proxy_pass http://backend_servers;
access_log /var/log/nginx/myapp_proxy_access.log proxy_detailed buffer=64k flush=10s;
error_log /var/log/nginx/myapp_error.log;
}
location /static {
root /var/www/static;
access_log /var/log/nginx/myapp_static_access.log custom_basic;
}
}
Trong ví dụ trên, access_log cho / sử dụng định dạng proxy_detailed và có thêm tùy chọn buffer=64k flush=10s. Điều này có nghĩa là Nginx sẽ lưu trữ nhật ký trong bộ nhớ đệm (buffer) 64KB. Nhật ký sẽ được ghi ra đĩa khi buffer đầy hoặc sau mỗi 10 giây, tùy điều kiện nào đến trước. Điều này giúp giảm số lượng thao tác I/O nhỏ.
Luôn nhớ bật bộ nhớ cache cho file nhật ký bằng chỉ thị open_log_file_cache ở cấp http để cải thiện hiệu suất chung của máy chủ.
Xác minh Đầu ra Nhật ký
Để kiểm tra định dạng nhật ký đã cấu hình, bạn có thể gửi các yêu cầu thử nghiệm tới Nginx và kiểm tra nội dung file nhật ký.
Giả sử bạn đã cấu hình proxy_detailed và gửi một yêu cầu tới máy chủ Nginx đang chạy ở địa chỉ 192.168.1.100:
curl -H "X-Forwarded-For: 10.0.0.5" http://192.168.1.100/service/data
Một mục nhật ký tương tự có thể xuất hiện trong file /var/log/nginx/myapp_proxy_access.log:
192.168.1.10 - - [01/Jan/2023:10:30:05 +0700] "GET /service/data HTTP/1.1" 200 1547 "http://myapp.com/" "Mozilla/5.0 (Windows NT 10.0)" "10.0.0.5" 0.045 0.020 192.168.1.50:8080 200
Phân tích dòng nhật ký này:
192.168.1.10: Là địa chỉ IP của máy khách ($remote_addr).- -: Không có tên người dùng xác thực ($remote_user) và không có referer cụ thể (hoặc nó đã bị loại bỏ).[01/Jan/2023:10:30:05 +0700]: Thời gian yêu cầu ($time_local)."GET /service/data HTTP/1.1": Dòng yêu cầu HTTP đầy đủ ($request).200: Mã trạng thái HTTP của phản hồi từ Nginx ($status).1547: Kích thước phản hồi được gửi cho máy khách ($body_bytes_sent)."http://myapp.com/": Trang giới thiệu ($http_referer)."Mozilla/5.0 (Windows NT 10.0)": Chuỗi User-Agent của máy khách ($http_user_agent)."10.0.0.5": Địa chỉ IP của máy khách ban đầu từ headerX-Forwarded-For($http_x_forwarded_for).0.045: Tổng thời gian xử lý yêu cầu bởi Nginx ($request_time).0.020: Thời gian phản hồi từ máy chủ upstream ($upstream_response_time).192.168.1.50:8080: Địa chỉ và cổng của máy chủ upstream đã xử lý yêu cầu ($upstream_addr).200: Mã trạng thái HTTP của phản hồi từ máy chủ upstream ($upstream_status).
Nhờ định dạng nhật ký chi tiết này, bạn có thể dễ dàng theo dõi hiệu suất, gỡ lỗi các vấn đề liên quan đến backend và hiểu rõ hơn về luồng yêu cầu qua máy chủ proxy Nginx.