本文目录导读:

在 PHP 项目中配置 ELK(Elasticsearch + Logstash + Kibana)进行日志收集,我给您一个完整的配置方案:
整体架构
PHP应用 → 日志文件/直接发送 → Filebeat → Logstash → Elasticsearch → Kibana
PHP 端配置
使用 Monolog(推荐)
// composer require monolog/monolog
use Monolog\Logger;
use Monolog\Handler\SocketHandler;
use Monolog\Formatter\JsonFormatter;
// 创建日志实例
$log = new Logger('php_app');
// 使用 TCP Socket 直接发送到 Logstash
$handler = new SocketHandler("tcp://logstash-host:5000");
$handler->setFormatter(new JsonFormatter());
$log->pushHandler($handler);
// 同时写本地文件备份
$log->pushHandler(new \Monolog\Handler\StreamHandler('/var/log/php/app.log', Logger::DEBUG));
// 使用示例
$log->info('用户登录', ['user_id' => 123, 'ip' => '192.168.1.1']);
$log->error('数据库连接失败', ['db' => 'mysql', 'error' => 'connection refused']);
使用 filebeat 收集日志文件
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/php/*.log
fields:
app: php_app
env: production
fields_under_root: true
output.logstash:
hosts: ["logstash-host:5044"]
Logstash 配置
接收 Filebeat 日志
# logstash-pipeline.conf
input {
beats {
port => 5044
client_inactivity_timeout => 3600
}
}
filter {
if [fields][app] == "php_app" {
# 解析 JSON 日志
json {
source => "message"
target => "php_log"
remove_field => ["message"]
}
# 添加时间戳
date {
match => ["timestamp", "ISO8601"]
target => "@timestamp"
}
# 解析 PHP 错误信息
grok {
match => { "message" => "\[%{TIMESTAMP_ISO8601:log_time}\] %{LOGLEVEL:log_level} %{GREEDYDATA:log_message}" }
tag_on_failure => []
}
# 解析 IP 地址地理位置
geoip {
source => "[php_log][ip]"
target => "geoip"
add_field => ["geoip", "geo"]
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "php-logs-%{+YYYY.MM.dd}"
user => "elastic"
password => "your_password"
}
}
直接接收 PHP Socket
input {
tcp {
port => 5000
type => "php-json"
codec => json_lines
}
}
filter {
if [type] == "php-json" {
json {
source => "message"
target => "php_log"
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "php-logs-%{+YYYY.MM.dd}"
}
}
Elasticsearch 配置
# elasticsearch.yml cluster.name: "production-cluster" node.name: "es-node-1" network.host: 0.0.0.0 http.port: 9200 discovery.type: single-node # 安全配置(推荐生产环境启用) xpack.security.enabled: true xpack.security.transport.ssl.enabled: true
Kibana 配置
# kibana.yml server.port: 5601 server.host: "0.0.0.0" elasticsearch.hosts: ["http://elasticsearch:9200"] elasticsearch.username: "kibana_system" elasticsearch.password: "your_password" # 设置默认索引模式 kibana.defaultAppId: "discover"
Docker Compose 部署示例
# docker-compose.yml
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"
volumes:
- es_data:/usr/share/elasticsearch/data
logstash:
image: docker.elastic.co/logstash/logstash:7.15.0
volumes:
- ./logstash/:/usr/share/logstash/pipeline/
ports:
- "5044:5044"
- "5000:5000"
environment:
- LS_JAVA_OPTS=-Xms256m -Xmx256m
kibana:
image: docker.elastic.co/kibana/kibana:7.15.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
filebeat:
image: docker.elastic.co/beats/filebeat:7.15.0
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /var/log/php:/var/log/php:ro
volumes:
es_data:
PHP 日志规范建议
// 统一日志格式
class LogManager {
public static function info($message, $context = []) {
$logData = [
'timestamp' => date('c'),
'level' => 'INFO',
'message' => $message,
'context' => $context,
'request_id' => uniqid(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'request_ip' => $_SERVER['REMOTE_ADDR'] ?? '',
'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
'method' => $_SERVER['REQUEST_METHOD'] ?? '',
'execution_time' => microtime(true) - PHP_APP_START_TIME ?? 0
];
return $logData;
}
}
Kibana 查询示例
// 查询特定应用日志
{
"query": {
"bool": {
"must": [
{ "match": { "php_log.level": "ERROR" } },
{ "term": { "app": "php_app" } }
],
"filter": [
{ "range": { "@timestamp": { "gte": "now-1h" } } }
]
}
}
}
性能优化建议
- 批量发送:使用
Monolog的BufferHandler批量发送日志 - 异步记录:使用
消息队列如 RabbitMQ 做缓冲 - 索引管理:设置 ILM(Index Lifecycle Management)策略
- 日志分级:生产环境只记录 WARNING 级别以上
这样配置后,你可以:
- 实时搜索 PHP 应用日志
- 可视化错误率和请求量
- 设置告警规则
- 快速定位问题
需要我详细解释某个部分吗?