本文目录导读:

对于PHP项目的远程日志对接收集,可以考虑以下几种主流方案:
ELK/EFK 方案(最常用)
使用 Filebeat + Logstash + Elasticsearch + Kibana
PHP端配置:
// 使用 Monolog 日志库
use Monolog\Logger;
use Monolog\Handler\SocketHandler;
$log = new Logger('app');
$handler = new SocketHandler('tcp://logstash-server:5000');
$handler->setFormatter(new \Monolog\Formatter\JsonFormatter());
$log->pushHandler($handler);
Filebeat 配置:
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/php/*.log
output.logstash:
hosts: ["logstash:5044"]
Rsyslog 方案(轻量级)
PHP端配置:
// PHP syslog 发送
openlog('myapp', LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog(LOG_WARNING, "User login failed: {$username}");
closelog();
Rsyslog 服务端配置:
# /etc/rsyslog.conf $ModLoad imudp $UDPServerRun 514 $template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log" *.* ?RemoteLogs
Fluentd 方案(高性能)
PHP端使用 Fluentd Logger:
use Fluent\Logger\FluentLogger;
$logger = new FluentLogger("localhost", "24224");
$logger->post("app.access", [
"method" => $_SERVER['REQUEST_METHOD'],
"uri" => $_SERVER['REQUEST_URI'],
"time" => time()
]);
Fluentd 配置:
<source> @type forward port 24224 </source> <match app.**> @type elasticsearch host localhost port 9200 index_name app_logs </match>
Redis 缓冲方案(高并发场景)
// PHP 端
$redis = new Redis();
$redis->connect('redis-server', 6379);
$redis->rPush('log_queue', json_encode([
'timestamp' => date('Y-m-d H:i:s'),
'level' => 'ERROR',
'message' => 'Database connection failed',
'trace' => debug_backtrace()
]));
// 消费端脚本(使用 Supervisor 守护)
$redis = new Redis();
$redis->connect('redis-server', 6379);
while ($log = $redis->lPop('log_queue')) {
// 发送到日志系统
sendToLogSystem($log);
}
HTTP API 推送方案
// PHP 端
class RemoteLogger {
private $apiUrl = 'https://log-collector.yourdomain.com/api/logs';
public function send($level, $message, $context = []) {
$data = [
'app_id' => 'your-app-id',
'token' => 'your-auth-token',
'level' => $level,
'message' => $message,
'context' => $context,
'timestamp' => date('c'),
'host' => gethostname(),
'php_version'=> PHP_VERSION
];
$ch = curl_init($this->apiUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_TIMEOUT, 2); // 非阻塞
curl_exec($ch);
curl_close($ch);
}
}
收集端 API:
// 接收并存储
public function store(Request $request) {
$log = $request->all();
// 验证 token
// 存储到 Elasticsearch/数据库
// 发送到消息队列
return response()->json(['status' => 'ok']);
}
最佳实践建议
异步处理(避免影响主流程)
// 使用进程通信
function asyncLog($message) {
$pipe = '/tmp/php_log_pipe';
if (!file_exists($pipe)) {
posix_mkfifo($pipe, 0666);
}
$pid = pcntl_fork();
if ($pid == -1) {
// fork 失败,直接写入
} else if ($pid) {
// 父进程继续
} else {
// 子进程处理日志
$fp = fopen($pipe, 'w');
fwrite($fp, json_encode($message));
fclose($fp);
exit(0);
}
}
日志格式规范化
// 统一日志格式
function formatLog($level, $message, $context = []) {
return [
'id' => uniqid(),
'timestamp' => (new DateTime())->format('c'),
'level' => $level,
'message' => $message,
'context' => $context,
'host' => gethostname(),
'pid' => getmypid(),
'memory' => memory_get_usage(true),
'request_id'=> $_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid()
];
}
推荐组合方案
对于大多数场景,推荐:
- 中小项目:Rsyslog + Logstash + Elasticsearch
- 大型项目:Filebeat + Kafka + Logstash + Elasticsearch
- 云原生:Fluentd + 阿里云日志服务/SLS
最终选择取决于:
- 日志量大小(每天多少GB)
- 实时性要求
- 系统复杂度
- 运维能力
建议先从小方案开始,随着业务增长逐步升级。