如何用PHP项目使用ELK?

wen java案例 3

本文目录导读:

如何用PHP项目使用ELK?

  1. 整体架构方案
  2. 主流实现方案
  3. Monolog集成方案(最推荐)
  4. Logstash格式化建议
  5. Kibana可视化配置
  6. 性能优化建议

在PHP项目中使用ELK(Elasticsearch, Logstash, Kibana)栈,主要有以下几种方式,我来为你详细说明每种方案的具体实现:

整体架构方案

PHP应用 → 日志文件/直接发送 → Logstash → Elasticsearch → Kibana

主流实现方案

方案1:使用Filebeat + Logstash(推荐)

适用于多服务器、高并发场景,性能影响最小。

步骤:

  1. PHP端配置日志
    // 统一日志格式,推荐使用Monolog
    use Monolog\Logger;
    use Monolog\Handler\StreamHandler;
    use Monolog\Formatter\JsonFormatter;

$log = new Logger('app'); $handler = new StreamHandler('/var/log/php-app/app.log', Logger::INFO); $handler->setFormatter(new JsonFormatter()); $log->pushHandler($handler);

// 记录日志 $log->info('用户登录成功', [ 'user_id' => 123, 'ip' => '192.168.1.1', 'action' => 'login', 'timestamp' => time() ]);


2. **Filebeat配置** (`filebeat.yml`)
```yaml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/php-app/*.log
  json.keys_under_root: true
  json.overwrite_keys: true
output.logstash:
  hosts: ["localhost:5044"]
  1. Logstash配置 (logstash.conf)
    input {
    beats {
     port => 5044
    }
    }

filter { json { source => "message" }

date { match => ["timestamp", "UNIX"] target => "@timestamp" } }

output { elasticsearch { hosts => ["localhost:9200"] index => "php-app-logs-%{+YYYY.MM.dd}" } }


### 方案2:PHP直接发送到Logstash
适用于低并发、需要实时处理的小型应用。
```php
// 使用Guzzle HTTP客户端发送
use GuzzleHttp\Client;
class ElkLogger {
    private $client;
    private $logstashUrl;
    public function __construct($logstashUrl = 'http://localhost:5000') {
        $this->client = new Client();
        $this->logstashUrl = $logstashUrl;
    }
    public function log($level, $message, $context = []) {
        $data = [
            '@timestamp' => date('c'),
            'level' => $level,
            'message' => $message,
            'context' => $context,
            'app_name' => 'my-php-app',
            'environment' => getenv('APP_ENV') ?: 'production',
            'server_ip' => $_SERVER['SERVER_ADDR'] ?? 'unknown'
        ];
        try {
            $this->client->post($this->logstashUrl, [
                'json' => $data,
                'timeout' => 1 // 非阻塞
            ]);
        } catch (\Exception $e) {
            // 无法发送到ELK时,回退到文件日志
            error_log("ELK Logger failed: " . $e->getMessage());
        }
    }
    public function info($message, $context = []) {
        $this->log('info', $message, $context);
    }
    public function error($message, $context = []) {
        $this->log('error', $message, $context);
    }
}
// 使用示例
$logger = new ElkLogger();
$logger->info('用户注册成功', ['user_id' => 456, 'email' => 'test@example.com']);

Logstash HTTP输入配置:

input {
  http {
    port => 5000
    codec => json
  }
}
filter {
  # 处理时间戳
  date {
    match => ["@timestamp", "ISO8601"]
  }
}
output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "php-app-logs-%{+YYYY.MM.dd}"
  }
}

方案3:使用PHP Elasticsearch客户端直接写入

适用于需要精细化控制的场景。

// 安装: composer require elasticsearch/elasticsearch
use Elasticsearch\ClientBuilder;
class ElasticsearchLogger {
    private $client;
    private $index;
    public function __construct($hosts = ['localhost:9200'], $index = 'php-app-logs') {
        $this->client = ClientBuilder::create()
            ->setHosts($hosts)
            ->build();
        $this->index = $index;
    }
    public function log($level, $message, $context = []) {
        $params = [
            'index' => $this->index . '-' . date('Y.m.d'),
            'body' => [
                '@timestamp' => date('c'),
                'level' => $level,
                'message' => $message,
                'context' => $context,
                'app_name' => 'my-php-app',
                'environment' => getenv('APP_ENV') ?: 'production'
            ]
        ];
        try {
            $response = $this->client->index($params);
            return $response['_id'];
        } catch (\Exception $e) {
            error_log("Elasticsearch Logger failed: " . $e->getMessage());
            return false;
        }
    }
    // 批量写入,提高性能
    public function batchLog($entries) {
        $params = ['body' => []];
        foreach ($entries as $entry) {
            $params['body'][] = [
                'index' => [
                    '_index' => $this->index . '-' . date('Y.m.d')
                ]
            ];
            $params['body'][] = [
                '@timestamp' => $entry['timestamp'] ?? date('c'),
                'level' => $entry['level'],
                'message' => $entry['message'],
                'context' => $entry['context'] ?? []
            ];
        }
        try {
            return $this->client->bulk($params);
        } catch (\Exception $e) {
            error_log("Elasticsearch bulk failed: " . $e->getMessage());
            return false;
        }
    }
}

Monolog集成方案(最推荐)

Monolog是PHP最流行的日志库,有现成的ELK集成。

安装依赖

composer require monolog/monolog

配置Monolog Handler

use Monolog\Logger;
use Monolog\Handler\ElasticsearchHandler;
use Monolog\Formatter\ElasticsearchFormatter;
use Elasticsearch\ClientBuilder;
// 创建Elasticsearch客户端
$client = ClientBuilder::create()
    ->setHosts(['localhost:9200'])
    ->build();
// 创建日志
$logger = new Logger('my_app');
// Elasticsearch Handler
$options = [
    'index' => 'monolog-' . date('Y.m.d'),
    'type' => 'log'
];
$handler = new ElasticsearchHandler($client, $options);
$handler->setFormatter(new ElasticsearchFormatter('monolog-' . date('Y.m.d'), 'log'));
$logger->pushHandler($handler);
// 使用
$logger->info('用户行为记录', [
    'user_id' => 123,
    'action' => 'purchase',
    'amount' => 99.99
]);
$logger->error('数据库错误', [
    'sql' => 'SELECT * FROM users',
    'error_code' => 1045
]);

Logstash格式化建议

确保PHP日志包含这些关键字段:

// 推荐的日志结构
[
    'timestamp' => date('c'),
    'level' => 'INFO',
    'message' => '日志内容',
    'app_name' => 'my-php-app',
    'environment' => 'production',
    'request_id' => uniqid(),
    'user_id' => $userId,
    'ip' => $_SERVER['REMOTE_ADDR'],
    'user_agent' => $_SERVER['HTTP_USER_AGENT'],
    'uri' => $_SERVER['REQUEST_URI'],
    'method' => $_SERVER['REQUEST_METHOD'],
    'duration' => $endTime - $startTime, // 请求耗时
    'extra' => [] // 自定义数据
]

Kibana可视化配置

在Kibana中创建索引模式:

  1. 打开 Kibana → Management → Index Patterns
  2. 创建 php-app-logs-* 索引模式
  3. 配置时间字段为 @timestamp

常用可视化建议:

  • 应用错误率仪表板:根据 level=ERROR 过滤
  • API响应时间分析:使用 duration 字段
  • 用户行为追踪:根据 user_id 和 action 字段
  • 错误追踪:按 error_code 和 message 聚合

性能优化建议

  1. 使用缓冲写入:批量写入而非单条写入
  2. 异步处理:使用消息队列如RabbitMQ
  3. 日志级别控制:生产环境只记录WARNING及以上级别
  4. 日志采样:高并发场景下只记录部分请求
  5. 索引生命周期管理:定期删除旧索引

对于大多数PHP项目,推荐使用 方案1(Filebeat+Logstash)Monolog集成方案,它们:

  • 对PHP应用性能影响最小
  • 易于维护和扩展
  • 支持高并发场景
  • 提供更好的错误隔离

选择哪种方案主要取决于你的具体需求:实时性、并发量、团队技术栈等。

抱歉,评论功能暂时关闭!