当前位置: 首页 > news >正文

PHP服务器监控与性能指标采集

PHP服务器监控与性能指标采集

服务器监控是运维的重要环节。PHP可以直接采集系统指标,包括CPU、内存、磁盘、网络等。今天说说PHP服务器监控的实现。

PHP可以通过读取/proc文件系统获取系统状态。

```php
class SystemMonitor
{
public function getCpuUsage(): array
{
$cpuInfo = file_get_contents('/proc/stat');
preg_match('/^cpu\s+(.*)$/m', $cpuInfo, $matches);
$parts = preg_split('/\s+/', $matches[1]);

$total = array_sum($parts);
$idle = $parts[3];

return [
'user' => round($parts[0] / $total * 100, 2),
'system' => round($parts[2] / $total * 100, 2),
'idle' => round($idle / $total * 100, 2),
'iowait' => round(($parts[4] ?? 0) / $total * 100, 2),
];
}

public function getMemoryUsage(): array
{
$memInfo = file_get_contents('/proc/meminfo');
$data = [];
preg_match_all('/^(\w+):\s+(\d+)\skB$/m', $memInfo, $matches);

foreach ($matches[1] as $i => $name) {
$data[$name] = (int)$matches[2][$i];
}

$total = $data['MemTotal'] ?? 0;
$free = $data['MemFree'] ?? 0;
$available = $data['MemAvailable'] ?? $free;
$used = $total - $available;

return [
'total_mb' => round($total / 1024, 2),
'used_mb' => round($used / 1024, 2),
'free_mb' => round($available / 1024, 2),
'usage_percent' => $total > 0 ? round($used / $total * 100, 2) : 0,
];
}

public function getDiskUsage(): array
{
$path = '/';
return [
'total_gb' => round(disk_total_space($path) / 1024 / 1024 / 1024, 2),
'free_gb' => round(disk_free_space($path) / 1024 / 1024 / 1024, 2),
'used_gb' => round((disk_total_space($path) - disk_free_space($path)) / 1024 / 1024 / 1024, 2),
'usage_percent' => round((1 - disk_free_space($path) / disk_total_space($path)) * 100, 2),
];
}

public function getLoadAverage(): array
{
$load = sys_getloadavg();
return [
'1min' => round($load[0], 2),
'5min' => round($load[1], 2),
'15min' => round($load[2], 2),
];
}

public function getUptime(): array
{
$uptime = (int)file_get_contents('/proc/uptime');
return [
'seconds' => $uptime,
'formatted' => sprintf(
'%d天 %02d:%02d:%02d',
intdiv($uptime, 86400),
intdiv($uptime % 86400, 3600),
intdiv($uptime % 3600, 60),
$uptime % 60
),
];
}

public function getNetworkStats(): array
{
$netInfo = file_get_contents('/proc/net/dev');
$interfaces = [];
preg_match_all('/^\s*(eth\d+|ens\d+|enp\d+s\d+):\s*(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/m', $netInfo, $matches);

foreach ($matches[1] as $i => $iface) {
$interfaces[$iface] = [
'rx_bytes' => (int)$matches[2][$i],
'tx_bytes' => (int)$matches[3][$i],
];
}

return $interfaces;
}

public function getPhpInfo(): array
{
return [
'version' => PHP_VERSION,
'sapi' => php_sapi_name(),
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'opcache_enabled' => function_exists('opcache_get_status') ? true : false,
];
}

public function getAllMetrics(): array
{
return [
'timestamp' => date('Y-m-d H:i:s'),
'uptime' => $this->getUptime(),
'cpu' => $this->getCpuUsage(),
'memory' => $this->getMemoryUsage(),
'disk' => $this->getDiskUsage(),
'load' => $this->getLoadAverage(),
'network' => $this->getNetworkStats(),
'php' => $this->getPhpInfo(),
];
}
}

$monitor = new SystemMonitor();
$metrics = $monitor->getAllMetrics();
echo json_encode($metrics, JSON_PRETTY_PRINT) . "\n";
?>
```

监控指标的持久化和告警。

```php
class MetricsStorage
{
private PDO $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
$this->initTable();
}

private function initTable(): void
{
$this->pdo->exec("
CREATE TABLE IF NOT EXISTS metrics (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
metric_name VARCHAR(100) NOT NULL,
metric_value DECIMAL(15, 4) NOT NULL,
tags JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_name_created (metric_name, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
");
}

public function store(string $name, float $value, array $tags = []): void
{
$stmt = $this->pdo->prepare("INSERT INTO metrics (metric_name, metric_value, tags) VALUES (?, ?, ?)");
$stmt->execute([$name, $value, json_encode($tags)]);
}

public function getHistory(string $name, int $minutes = 60): array
{
$stmt = $this->pdo->prepare("
SELECT metric_value, created_at FROM metrics
WHERE metric_name = ? AND created_at > DATE_SUB(NOW(), INTERVAL ? MINUTE)
ORDER BY created_at ASC
");
$stmt->execute([$name, $minutes]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

public function cleanup(int $keepDays = 30): int
{
$stmt = $this->pdo->prepare("DELETE FROM metrics WHERE created_at < DATE_SUB(NOW(), INTERVAL ? DAY)");
$stmt->execute([$keepDays]);
return $stmt->rowCount();
}
}

class AlertRule
{
public function __construct(
public string $metric,
public float $threshold,
public string $operator = '>',
public string $message = ''
) {}

public function check(float $value): bool
{
return match ($this->operator) {
'>' => $value > $this->threshold,
'<' => $value < $this->threshold,
'>=' => $value >= $this->threshold,
'<=' => $value <= $this->threshold,
'==' => $value == $this->threshold,
default => false,
};
}
}

class AlertManager
{
private array $rules = [];

public function addRule(AlertRule $rule): void
{
$this->rules[] = $rule;
}

public function checkMetrics(array $metrics): array
{
$alerts = [];

foreach ($this->rules as $rule) {
$value = $this->extractMetric($metrics, $rule->metric);
if ($value !== null && $rule->check($value)) {
$alerts[] = [
'metric' => $rule->metric,
'value' => $value,
'threshold' => $rule->threshold,
'message' => $rule->message ?: "{$rule->metric} {$rule->operator} {$rule->threshold},当前值: {$value}",
'time' => date('Y-m-d H:i:s'),
];
}
}

return $alerts;
}

private function extractMetric(array $metrics, string $path): ?float
{
$parts = explode('.', $path);
$current = $metrics;

foreach ($parts as $part) {
if (!isset($current[$part])) return null;
$current = $current[$part];
}

return is_numeric($current) ? (float)$current : null;
}
}

$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$storage = new MetricsStorage($pdo);
$monitor = new SystemMonitor();
$alertManager = new AlertManager();

$alertManager->addRule(new AlertRule('cpu.user', 80, '>', 'CPU使用率超过80%'));
$alertManager->addRule(new AlertRule('memory.usage_percent', 90, '>', '内存使用率超过90%'));
$alertManager->addRule(new AlertRule('disk.usage_percent', 85, '>', '磁盘使用率超过85%'));
$alertManager->addRule(new AlertRule('load.1min', 8, '>', '系统负载过高'));

// 采集并检查
$metrics = $monitor->getAllMetrics();
$storage->store('cpu.user', $metrics['cpu']['user']);
$storage->store('memory.usage', $metrics['memory']['usage_percent']);
$storage->store('disk.usage', $metrics['disk']['usage_percent']);

$alerts = $alertManager->checkMetrics($metrics);
if (!empty($alerts)) {
foreach ($alerts as $alert) {
echo "[告警] {$alert['message']}\n";
}
} else {
echo "系统运行正常\n";
}
?>
```

服务器监控是运维自动化的基础。PHP虽然不是专门的监控工具,但通过读取系统文件和调用系统命令,可以实现基本的监控功能。生产环境建议使用Prometheus、Grafana等专业的监控系统。

http://www.cnnetsun.cn/news/2705032.html

相关文章:

  • 别再只玩AutoGPT了!手把手教你用Python+LangChain从零搭建一个ReAct智能体(附完整代码)
  • 告别虚拟机卡顿:用WSL2+Docker搭建韦东山同款嵌入式Linux开发环境(保姆级避坑)
  • 空间转录组去卷积工具怎么选?CARD、Cell2location、SPOTlight实战对比与避坑指南
  • 告别DOM和JAXB!用Hutool的XmlUtil搞定XML读写,5分钟上手Java数据交换
  • 别再只用PLY和OBJ了!聊聊PCL库的‘亲儿子’PCD格式,为什么它才是点云处理的‘瑞士军刀’?
  • 卫星像片图
  • 新手别慌!用Pikachu靶场从零理解SQL注入的10种花样(附详细Payload)
  • 纳什均衡:博弈论中的“非合作”思想及其工程应用
  • 从CHI 2011看人机交互范式演进:环境式交互与无触控技术实践
  • Spring项目启动报NoClassDefFoundError?别慌,手把手教你搞定Commons Logging依赖冲突
  • GLIP实战:用自定义提示词玩转零样本目标检测,从‘沙发电视’到‘泡泡头手办’
  • 基于机构位移分析的索杆张力结构形态解析方案【附仿真】
  • 避坑指南:Proteus 8.6在Win10/Win11系统下的安装常见问题与解决方案
  • 告别手动下载!用Flutter auto_updater给你的Windows/Mac桌面应用加上自动更新(保姆级配置流程)
  • 告别环境配置焦虑:用PHPStudy+VSCode搭建PHP调试环境,手把手教你搞定XDebug
  • 手把手教你为TMS320F28377D项目移植IQMath库(附16位/30位精度选择指南)
  • 别再乱配了!华为交换机MQC实战:用流策略精准限制不同部门网速(附完整配置命令)
  • 别再死记硬背了!用生活中的例子秒懂CPU、内存和I/O(比如点奶茶)
  • Microsoft Biology Foundation:高性能.NET生物信息学框架实战指南
  • 别光顾着‘爆库’:用sqli-labs靶场系统梳理SQL注入的完整攻击链(附思维导图)
  • NLP如何重塑SEO:从关键词匹配到语义理解的实战指南
  • 别再只盯着损失曲线了!可视化卷积VAE潜在空间,教你‘看懂’模型学到了什么
  • 保姆级教程:用ESPFlashDownloadTool_v3.6.3给NodeMCU烧录固件(附Flash地址详解)
  • FPGA时序约束入门:手把手教你用Vivado给跨时钟域路径‘上保险’
  • 从‘存不了Emoji’到‘乱码’:一次搞懂MySQL字符集utf8mb4的完整配置流程
  • 别再死记硬背OSI七层模型了!用eNSP+Wireshark抓个包,亲手‘看见’网络协议
  • Mask2Former二分类实战:当语义分割遇上ADE20K格式数据集,我是这样调整配置文件的
  • BetterGI完全指南:如何用AI技术让原神游戏体验更轻松
  • 从实验室到桌面:用Python和空间光调制器(SLM)仿真搭建你自己的计算鬼成像系统
  • Doris Array类型在智慧交通项目中的实战:如何用ARRAY<VARCHAR>高效存储路口多维度指标?