本文目录导读:

我来帮你设计一个PHP项目指标收集并与Prometheus集成的方案。
基础架构
graph LR
A[PHP应用] --> B[Prometheus客户端]
B --> C[/metrics端点]
C --> D[Prometheus Server]
D --> E[Grafana]
安装与配置
安装Prometheus PHP客户端
composer require promphp/prometheus_client_php
基础配置示例
<?php
// src/Metrics/PrometheusMetrics.php
use Prometheus\CollectorRegistry;
use Prometheus\Storage\Redis;
use Prometheus\Storage\APC;
use Prometheus\RenderTextFormat;
class PrometheusMetrics
{
private CollectorRegistry $registry;
private static ?self $instance = null;
public function __construct()
{
// 选择存储后端
$adapter = new Redis(['host' => '127.0.0.1', 'port' => 6379]);
// 或使用APC(单机适用)
// $adapter = new APC();
$this->registry = new CollectorRegistry($adapter);
}
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// HTTP请求指标
public function trackRequest(string $method, string $endpoint, int $statusCode, float $duration): void
{
$counter = $this->registry->getOrRegisterCounter(
'app',
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status_code']
);
$counter->incBy(1, [$method, $endpoint, (string)$statusCode]);
$histogram = $this->registry->getOrRegisterHistogram(
'app',
'http_request_duration_seconds',
'HTTP request duration',
['method', 'endpoint'],
[0.1, 0.5, 1, 2, 5, 10]
);
$histogram->observe($duration, [$method, $endpoint]);
}
// 数据库查询指标
public function trackQuery(string $queryType, string $table, float $duration): void
{
$histogram = $this->registry->getOrRegisterHistogram(
'app',
'db_query_duration_seconds',
'Database query duration',
['query_type', 'table'],
[0.01, 0.05, 0.1, 0.5, 1, 2]
);
$histogram->observe($duration, [$queryType, $table]);
}
// 业务指标
public function incBusinessMetric(string $metricName, array $labels = []): void
{
$counter = $this->registry->getOrRegisterCounter(
'app_business',
$metricName,
'Business metric: ' . $metricName,
array_keys($labels)
);
$counter->incBy(1, array_values($labels));
}
// 渲染metrics
public function render(): string
{
$renderer = new RenderTextFormat();
return $renderer->render($this->registry->getMetricFamilySamples());
}
}
中间件实现
Laravel中间件
<?php
// app/Http/Middleware/PrometheusMiddleware.php
namespace App\Http\Middleware;
use Closure;
use App\Metrics\PrometheusMetrics;
class PrometheusMiddleware
{
public function handle($request, Closure $next)
{
$startTime = microtime(true);
$response = $next($request);
$duration = microtime(true) - $startTime;
$metrics = PrometheusMetrics::getInstance();
$metrics->trackRequest(
$request->method(),
$request->path(),
$response->status(),
$duration
);
return $response;
}
}
Symfony中间件
<?php
// src/Middleware/PrometheusMiddleware.php
namespace App\Middleware;
use PrometheusMetrics;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class PrometheusMiddleware implements HttpKernelInterface
{
private HttpKernelInterface $app;
public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = true)
{
$start = microtime(true);
$response = $this->app->handle($request, $type, $catch);
$duration = microtime(true) - $start;
$metrics = PrometheusMetrics::getInstance();
$metrics->trackRequest($request->getMethod(), $request->getPathInfo(), $response->getStatusCode(), $duration);
return $response;
}
}
Metrics端点
<?php
// routes/api.php (Laravel)
// 或直接在入口文件
Route::get('/metrics', function () {
$metrics = PrometheusMetrics::getInstance();
// 添加系统指标
$metrics->registry->getOrRegisterGauge(
'system',
'memory_usage_bytes',
'Current memory usage'
)->set(memory_get_usage(true));
$metrics->registry->getOrRegisterGauge(
'system',
'memory_peak_usage_bytes',
'Peak memory usage'
)->set(memory_get_peak_usage(true));
return response($metrics->render(), 200, [
'Content-Type' => 'text/plain; charset=utf-8'
]);
});
Prometheus配置
# prometheus.yml
scrape_configs:
- job_name: 'php_app'
scrape_interval: 15s
static_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
- job_name: 'php_app_advanced'
scrape_interval: 10s
metrics_path: '/metrics'
static_configs:
- targets:
- 'app1.example.com:8080'
- 'app2.example.com:8080'
relabel_configs:
- source_labels: [__address__]
regex: '(.*):.*'
target_label: instance
replacement: '${1}'
自定义业务指标
<?php
// Services/BusinessMetrics.php
class BusinessMetrics
{
private PrometheusMetrics $metrics;
public function __construct()
{
$this->metrics = PrometheusMetrics::getInstance();
}
// 用户注册指标
public function trackUserRegistration(string $source, string $country): void
{
$this->metrics->registry->getOrRegisterCounter(
'business',
'user_registrations_total',
'Total user registrations',
['source', 'country']
)->incBy(1, [$source, $country]);
}
// 订单指标
public function trackOrder(string $status, string $paymentMethod, float $amount): void
{
$this->metrics->registry->getOrRegisterCounter(
'business',
'orders_total',
'Total orders',
['status', 'payment_method']
)->incBy(1, [$status, $paymentMethod]);
$this->metrics->registry->getOrRegisterCounter(
'business',
'order_amount_total',
'Total order amount',
['status']
)->incBy($amount, [$status]);
}
// 并发用户数
public function trackConcurrentUsers(int $count): void
{
$this->metrics->registry->getOrRegisterGauge(
'business',
'concurrent_users',
'Number of concurrent users'
)->set($count);
}
// 队列指标
public function trackQueue(string $queueName, int $size, int $processed): void
{
$this->metrics->registry->getOrRegisterGauge(
'queue',
'queue_size',
'Queue size',
['queue_name']
)->set($size, [$queueName]);
$this->metrics->registry->getOrRegisterCounter(
'queue',
'messages_processed_total',
'Total messages processed',
['queue_name']
)->incBy($processed, [$queueName]);
}
}
Redis性能指标监控
<?php
// Monitoring/RedisMonitor.php
class RedisMonitor
{
private PrometheusMetrics $metrics;
private \Redis $redis;
public function __construct(\Redis $redis)
{
$this->redis = $redis;
$this->metrics = PrometheusMetrics::getInstance();
}
public function collectRedisMetrics(): void
{
$info = $this->redis->info();
// Redis关键指标
$gauges = [
'redis_connected_clients' => $info['connected_clients'],
'redis_used_memory_bytes' => $info['used_memory'],
'redis_used_memory_rss_bytes' => $info['used_memory_rss'],
'redis_hit_rate' => $this->calculateHitRate($info),
'redis_instantaneous_ops_per_sec' => $info['instantaneous_ops_per_sec'],
'redis_keyspace_hits' => $info['keyspace_hits'],
'redis_keyspace_misses' => $info['keyspace_misses']
];
foreach ($gauges as $name => $value) {
$this->metrics->registry->getOrRegisterGauge(
'redis',
$name,
'Redis metric: ' . $name
)->set($value);
}
}
private function calculateHitRate(array $info): float
{
$hits = $info['keyspace_hits'];
$misses = $info['keyspace_misses'];
$total = $hits + $misses;
return $total > 0 ? ($hits / $total) * 100 : 0;
}
}
Grafana仪表板配置
{
"dashboard": {: "PHP Application Metrics",
"panels": [
{
"title": "HTTP Requests Rate",
"type": "graph",
"targets": [
{
"expr": "rate(app_http_requests_total[5m])",
"legendFormat": "{{method}} {{endpoint}}"
}
]
},
{
"title": "Request Duration (95th Percentile)",
"type": "heatmap",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(app_http_request_duration_seconds_bucket[5m])) by (le))"
}
]
},
{
"title": "Database Query Duration",
"type": "graph",
"targets": [
{
"expr": "rate(app_db_query_duration_seconds_sum[5m]) / rate(app_db_query_duration_seconds_count[5m])",
"legendFormat": "{{query_type}} - {{table}}"
}
]
},
{
"title": "System Memory",
"type": "gauge",
"targets": [
{
"expr": "system_memory_usage_bytes"
}
]
}
]
}
}
性能优化建议
批量采集
<?php
// 使用APCu本地缓存,减少Redis写入
class BatchMetricsCollector
{
private array $buffer = [];
private int $bufferSize = 100;
public function record(string $metric, array $labels, float $value): void
{
$this->buffer[] = [
'metric' => $metric,
'labels' => $labels,
'value' => $value,
'timestamp' => microtime(true)
];
if (count($this->buffer) >= $this->bufferSize) {
$this->flush();
}
}
public function flush(): void
{
// 批量写入Redis或数据库
// ...
$this->buffer = [];
}
}
异步发送
<?php
// 使用消息队列异步处理
class AsyncMetricsSender
{
private Queue $queue;
public function send(array $metrics): void
{
// 将metrics推送到消息队列
$this->queue->push(json_encode($metrics));
}
}
Alerts规则
# alerts.yml
groups:
- name: php_app_alerts
rules:
- alert: HighErrorRate
expr: rate(app_http_requests_total{status_code=~"5.."}[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
description: "Error rate is {{ $value }} for the last 5 minutes"
- alert: SlowRequests
expr: histogram_quantile(0.95, rate(app_http_request_duration_seconds_bucket[5m])) > 2
for: 5m
labels:
severity: warning
annotations:
description: "95th percentile request duration is {{ $value }}s"
- alert: HighMemoryUsage
expr: system_memory_usage_bytes > 500000000
for: 10m
labels:
severity: warning
annotations:
description: "Memory usage is {{ $value }} bytes"
这套方案提供了完整的PHP与Prometheus集成方案,覆盖了基础监控、业务指标、性能优化和告警配置,你可以根据实际需求调整存储后端和具体指标。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播