本文目录导读:

为PHP项目设置请求日志,有以下几种常用方法,从简单到完整逐步介绍:
基础方法:PHP内置错误日志
php.ini 配置:
log_errors = On error_log = /var/log/php_errors.log ; 记录所有错误级别 error_reporting = E_ALL
代码中使用 error_log():
error_log("用户请求:{$_SERVER['REQUEST_URI']}", 3, '/var/log/requests.log');
手动实现请求日志中间件
<?php
class RequestLogger {
private $logFile;
public function __construct($logFile = '/var/log/requests.log') {
$this->logFile = $logFile;
$this->ensureLogDirectory();
}
public function log($request = null, $response = null) {
$logData = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'CLI',
'method' => $_SERVER['REQUEST_METHOD'] ?? 'CLI',
'uri' => $_SERVER['REQUEST_URI'] ?? '/',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'status_code' => http_response_code(),
'response_time_ms' => $this->getResponseTime(),
'request_body' => file_get_contents('php://input')
];
// 过滤敏感信息
$logData['request_body'] = $this->maskSensitiveData($logData['request_body']);
$logEntry = json_encode($logData) . PHP_EOL;
file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
}
private function getResponseTime() {
if (defined('REQUEST_START_TIME')) {
return round((microtime(true) - REQUEST_START_TIME) * 1000, 2);
}
return 0;
}
private function maskSensitiveData($data) {
$sensitive = ['password', 'token', 'credit_card', 'ssn'];
$decoded = json_decode($data, true);
if (is_array($decoded)) {
foreach ($sensitive as $key) {
if (isset($decoded[$key])) {
$decoded[$key] = str_repeat('*', strlen($decoded[$key]));
}
}
return json_encode($decoded);
}
return $data;
}
private function ensureLogDirectory() {
$dir = dirname($this->logFile);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
}
}
// 在项目入口文件使用
define('REQUEST_START_TIME', microtime(true));
$logger = new RequestLogger();
register_shutdown_function([$logger, 'log']);
使用框架集成(以Laravel为例)
Laravel 内置日志配置:
// config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'info',
'days' => 14,
],
],
// 创建中间件
php artisan make:middleware RequestLogger
// app/Http/Middleware/RequestLogger.php
public function handle($request, Closure $next)
{
$startTime = microtime(true);
$response = $next($request);
Log::channel('daily')->info('Request logged', [
'url' => $request->fullUrl(),
'method' => $request->method(),
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'status_code' => $response->status(),
'duration_ms' => round((microtime(true) - $startTime) * 1000, 2),
'request_data' => $this->filterSensitiveData($request->all()),
]);
return $response;
}
// 在 Kernel.php 注册中间件
protected $middleware = [
\App\Http\Middleware\RequestLogger::class,
];
使用 Monolog(独立PHP项目)
<?php
require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\JsonFormatter;
class RequestLogger {
private $logger;
public function __construct() {
$this->logger = new Logger('request');
// 按日期轮转日志
$handler = new RotatingFileHandler('/var/log/requests.log', 30, Logger::INFO);
// JSON格式输出,方便日志分析
$handler->setFormatter(new JsonFormatter());
$this->logger->pushHandler($handler);
}
public function logRequest() {
$this->logger->info('HTTP Request', [
'timestamp' => date('c'),
'method' => $_SERVER['REQUEST_METHOD'],
'path' => $_SERVER['REQUEST_URI'],
'query' => $_SERVER['QUERY_STRING'],
'ip' => $_SERVER['REMOTE_ADDR'],
'headers' => getallheaders(),
'body' => $this->getRequestBody(),
]);
}
private function getRequestBody() {
$body = file_get_contents('php://input');
return mb_strlen($body) > 10000 ? substr($body, 0, 10000) . '...' : $body;
}
}
// 使用
$logger = new RequestLogger();
$logger->logRequest();
最佳实践与配置示例
综合配置文件:
<?php
// config/logging.php
return [
'request_logging' => [
'enabled' => true,
'channel' => 'request',
'format' => 'json', // json, line, structured
'fields' => [
'basic' => ['method', 'uri', 'ip'],
'extended' => ['headers', 'query_params', 'request_body'],
'performance' => ['response_time', 'memory_usage'],
],
'sensitive_fields' => [
'password', 'token', 'secret', 'credit_card', 'ssn'
],
'exclude_paths' => [
'/health', '/metrics', '/favicon.ico'
],
'max_body_size' => 10000, // 限制请求体大小
'rotation' => [
'enabled' => true,
'max_files' => 30,
'max_size' => '100MB',
],
],
];
日志管理与分析建议
- 日志轮转:使用
logrotate或框架内置功能 - 使用ELK Stack:Elasticsearch + Logstash + Kibana
- 日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL
- 不要记录敏感数据:密码、令牌、信用卡信息
- 性能考虑:异步日志写入或使用消息队列
logrotate 配置示例:
/var/log/php-requests.log {
daily
rotate 30
compress
missingok
notifempty
create 0640 www-data www-data
postrotate
/usr/bin/killall -USR1 php-fpm
endscript
}
选择哪种方法取决于你的项目规模:
- 小型项目:使用 error_log() 或文件追加
- 中型项目:使用 Monolog 或框架内置功能
- 大型项目:使用 ELK Stack 或专业的日志服务
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播