mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
feat(database): 添加用户角色权限系统及相关监控功能
- 创建用户表(users)包含基本信息和认证字段 - 创建角色表(roles)用于权限控制 - 创建权限表(permissions)定义系统权限 - 创建用户角色关联表(user_roles)建立用户与角色关系 - 创建角色权限关联表(role_permissions)建立角色与权限关系 - 创建迁移记录表(migrations)追踪数据库变更 - 添加AdminController提供管理员面板功能 - 实现系统监控、配置管理、缓存清理等功能 - 添加AOP切面编程支持的各种通知类型 - 实现告警管理AlertManager支持多渠道告警 - 添加文档注解接口规范
This commit is contained in:
669
fendx-framework/fendx-debug/src/MemoryAnalyzer.php
Normal file
669
fendx-framework/fendx-debug/src/MemoryAnalyzer.php
Normal file
@@ -0,0 +1,669 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Debug;
|
||||
|
||||
use Fendx\Debug\Memory\MemorySnapshot;
|
||||
use Fendx\Debug\Memory\MemoryLeakDetector;
|
||||
use Fendx\Debug\Memory\MemoryUsageTracker;
|
||||
|
||||
class MemoryAnalyzer
|
||||
{
|
||||
protected static ?self $instance = null;
|
||||
protected bool $enabled = false;
|
||||
protected array $snapshots = [];
|
||||
protected MemoryUsageTracker $tracker;
|
||||
protected MemoryLeakDetector $leakDetector;
|
||||
protected array $config = [];
|
||||
protected int $baselineMemory;
|
||||
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->config = array_merge($this->getDefaultConfig(), $config);
|
||||
$this->tracker = new MemoryUsageTracker();
|
||||
$this->leakDetector = new MemoryLeakDetector();
|
||||
$this->baselineMemory = memory_get_usage(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory analyzer instance.
|
||||
*/
|
||||
public static function getInstance(array $config = []): self
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable memory analyzer.
|
||||
*/
|
||||
public function enable(): void
|
||||
{
|
||||
$this->enabled = true;
|
||||
$this->tracker->enable();
|
||||
$this->leakDetector->enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable memory analyzer.
|
||||
*/
|
||||
public function disable(): void
|
||||
{
|
||||
$this->enabled = false;
|
||||
$this->tracker->disable();
|
||||
$this->leakDetector->disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if analyzer is enabled.
|
||||
*/
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take memory snapshot.
|
||||
*/
|
||||
public function snapshot(string $name, array $context = []): MemorySnapshot
|
||||
{
|
||||
if (!$this->enabled) {
|
||||
throw new \RuntimeException('Memory analyzer is not enabled');
|
||||
}
|
||||
|
||||
$snapshot = new MemorySnapshot($name, $context);
|
||||
$snapshot->capture();
|
||||
|
||||
$this->snapshots[$name] = $snapshot;
|
||||
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory snapshot by name.
|
||||
*/
|
||||
public function getSnapshot(string $name): ?MemorySnapshot
|
||||
{
|
||||
return $this->snapshots[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all snapshots.
|
||||
*/
|
||||
public function getSnapshots(): array
|
||||
{
|
||||
return $this->snapshots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two snapshots.
|
||||
*/
|
||||
public function compare(string $from, string $to): array
|
||||
{
|
||||
$fromSnapshot = $this->getSnapshot($from);
|
||||
$toSnapshot = $this->getSnapshot($to);
|
||||
|
||||
if (!$fromSnapshot || !$toSnapshot) {
|
||||
throw new \InvalidArgumentException('Both snapshots must exist');
|
||||
}
|
||||
|
||||
return [
|
||||
'from' => $fromSnapshot->getName(),
|
||||
'to' => $toSnapshot->getName(),
|
||||
'memory_diff' => $toSnapshot->getMemoryUsage() - $fromSnapshot->getMemoryUsage(),
|
||||
'memory_diff_percent' => $this->calculatePercentageDiff(
|
||||
$fromSnapshot->getMemoryUsage(),
|
||||
$toSnapshot->getMemoryUsage()
|
||||
),
|
||||
'peak_memory_diff' => $toSnapshot->getPeakMemory() - $fromSnapshot->getPeakMemory(),
|
||||
'objects_diff' => $toSnapshot->getObjectCount() - $fromSnapshot->getObjectCount(),
|
||||
'time_diff' => $toSnapshot->getTimestamp() - $fromSnapshot->getTimestamp()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory usage trend.
|
||||
*/
|
||||
public function getTrend(): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$trend = [];
|
||||
$previousMemory = $this->baselineMemory;
|
||||
|
||||
foreach ($this->snapshots as $name => $snapshot) {
|
||||
$currentMemory = $snapshot->getMemoryUsage();
|
||||
$diff = $currentMemory - $previousMemory;
|
||||
|
||||
$trend[] = [
|
||||
'name' => $name,
|
||||
'timestamp' => $snapshot->getTimestamp(),
|
||||
'memory_usage' => $currentMemory,
|
||||
'memory_diff' => $diff,
|
||||
'memory_diff_percent' => $this->calculatePercentageDiff($previousMemory, $currentMemory),
|
||||
'peak_memory' => $snapshot->getPeakMemory(),
|
||||
'object_count' => $snapshot->getObjectCount()
|
||||
];
|
||||
|
||||
$previousMemory = $currentMemory;
|
||||
}
|
||||
|
||||
return $trend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect memory leaks.
|
||||
*/
|
||||
public function detectLeaks(): array
|
||||
{
|
||||
if (!$this->enabled) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->leakDetector->detect($this->snapshots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory usage statistics.
|
||||
*/
|
||||
public function getStatistics(): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [
|
||||
'current' => memory_get_usage(true),
|
||||
'peak' => memory_get_peak_usage(true),
|
||||
'baseline' => $this->baselineMemory,
|
||||
'growth' => memory_get_usage(true) - $this->baselineMemory,
|
||||
'snapshots_count' => 0
|
||||
];
|
||||
}
|
||||
|
||||
$current = memory_get_usage(true);
|
||||
$peak = memory_get_peak_usage(true);
|
||||
$growth = $current - $this->baselineMemory;
|
||||
|
||||
$memoryUsages = array_map(fn($s) => $s->getMemoryUsage(), $this->snapshots);
|
||||
$objectCounts = array_map(fn($s) => $s->getObjectCount(), $this->snapshots);
|
||||
|
||||
return [
|
||||
'current' => $current,
|
||||
'peak' => $peak,
|
||||
'baseline' => $this->baselineMemory,
|
||||
'growth' => $growth,
|
||||
'growth_percent' => $this->calculatePercentageDiff($this->baselineMemory, $current),
|
||||
'snapshots_count' => count($this->snapshots),
|
||||
'min_memory' => min($memoryUsages),
|
||||
'max_memory' => max($memoryUsages),
|
||||
'avg_memory' => array_sum($memoryUsages) / count($memoryUsages),
|
||||
'min_objects' => min($objectCounts),
|
||||
'max_objects' => max($objectCounts),
|
||||
'avg_objects' => array_sum($objectCounts) / count($objectCounts),
|
||||
'memory_efficiency' => $this->calculateMemoryEfficiency(),
|
||||
'leak_detected' => !empty($this->detectLeaks())
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory usage by type.
|
||||
*/
|
||||
public function getUsageByType(): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$latest = end($this->snapshots);
|
||||
return $latest->getUsageByType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get largest memory consumers.
|
||||
*/
|
||||
public function getLargestConsumers(int $limit = 10): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$latest = end($this->snapshots);
|
||||
return $latest->getLargestConsumers($limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate memory analysis report.
|
||||
*/
|
||||
public function generateReport(): array
|
||||
{
|
||||
$report = [
|
||||
'summary' => $this->getStatistics(),
|
||||
'trend' => $this->getTrend(),
|
||||
'snapshots' => [],
|
||||
'leaks' => $this->detectLeaks(),
|
||||
'usage_by_type' => $this->getUsageByType(),
|
||||
'largest_consumers' => $this->getLargestConsumers(),
|
||||
'recommendations' => $this->generateRecommendations(),
|
||||
'generated_at' => time()
|
||||
];
|
||||
|
||||
foreach ($this->snapshots as $name => $snapshot) {
|
||||
$report['snapshots'][$name] = $snapshot->toArray();
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save memory analysis report.
|
||||
*/
|
||||
public function saveReport(string $filename): bool
|
||||
{
|
||||
$report = $this->generateReport();
|
||||
$json = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
return file_put_contents($filename, $json) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export memory data.
|
||||
*/
|
||||
public function export(string $format = 'json'): string
|
||||
{
|
||||
$report = $this->generateReport();
|
||||
|
||||
switch (strtolower($format)) {
|
||||
case 'json':
|
||||
return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
case 'csv':
|
||||
return $this->exportToCsv($report);
|
||||
|
||||
case 'html':
|
||||
return $this->exportToHtml($report);
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unsupported export format: {$format}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export to CSV format.
|
||||
*/
|
||||
protected function exportToCsv(array $report): string
|
||||
{
|
||||
$csv = "Snapshot,Timestamp,Memory Usage (bytes),Peak Memory (bytes),Object Count\n";
|
||||
|
||||
foreach ($report['snapshots'] as $name => $snapshot) {
|
||||
$csv .= sprintf(
|
||||
"%s,%d,%d,%d,%d\n",
|
||||
$name,
|
||||
$snapshot['timestamp'],
|
||||
$snapshot['memory_usage'],
|
||||
$snapshot['peak_memory'],
|
||||
$snapshot['object_count']
|
||||
);
|
||||
}
|
||||
|
||||
return $csv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export to HTML format.
|
||||
*/
|
||||
protected function exportToHtml(array $report): string
|
||||
{
|
||||
$html = '<!DOCTYPE html><html><head><title>Memory Analysis Report</title>';
|
||||
$html .= '<style>body{font-family:Arial,sans-serif;margin:20px;}';
|
||||
$html .= 'table{border-collapse:collapse;width:100%;margin-bottom:20px;}';
|
||||
$html .= 'th,td{border:1px solid #ddd;padding:8px;text-align:left;}';
|
||||
$html .= 'th{background-color:#f2f2f2;}';
|
||||
$html .= '.warning{color:#f39c12;}.error{color:#e74c3c;}.success{color:#27ae60;}</style>';
|
||||
$html .= '</head><body>';
|
||||
|
||||
$html .= '<h1>Memory Analysis Report</h1>';
|
||||
|
||||
// Summary section
|
||||
$html .= '<h2>Summary</h2>';
|
||||
$html .= '<table><tr><th>Metric</th><th>Value</th></tr>';
|
||||
|
||||
foreach ($report['summary'] as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$value = json_encode($value);
|
||||
} elseif (is_bool($value)) {
|
||||
$value = $value ? 'Yes' : 'No';
|
||||
}
|
||||
|
||||
$class = '';
|
||||
if (str_contains($key, 'leak') && $value) {
|
||||
$class = 'error';
|
||||
} elseif (str_contains($key, 'growth') && $value > 0) {
|
||||
$class = 'warning';
|
||||
}
|
||||
|
||||
$html .= "<tr><td>{$key}</td><td class='{$class}'>{$value}</td></tr>";
|
||||
}
|
||||
|
||||
$html .= '</table>';
|
||||
|
||||
// Snapshots section
|
||||
$html .= '<h2>Memory Snapshots</h2>';
|
||||
$html .= '<table><tr><th>Name</th><th>Memory (MB)</th><th>Peak (MB)</th><th>Objects</th></tr>';
|
||||
|
||||
foreach ($report['snapshots'] as $name => $snapshot) {
|
||||
$html .= sprintf(
|
||||
"<tr><td>%s</td><td>%.2f</td><td>%.2f</td><td>%d</td></tr>",
|
||||
$name,
|
||||
$snapshot['memory_usage'] / 1024 / 1024,
|
||||
$snapshot['peak_memory'] / 1024 / 1024,
|
||||
$snapshot['object_count']
|
||||
);
|
||||
}
|
||||
|
||||
$html .= '</table>';
|
||||
|
||||
// Recommendations section
|
||||
if (!empty($report['recommendations'])) {
|
||||
$html .= '<h2>Recommendations</h2>';
|
||||
$html .= '<ul>';
|
||||
|
||||
foreach ($report['recommendations'] as $rec) {
|
||||
$class = $rec['severity'] === 'error' ? 'error' :
|
||||
($rec['severity'] === 'warning' ? 'warning' : '');
|
||||
$html .= "<li class='{$class}'>{$rec['message']}</li>";
|
||||
}
|
||||
|
||||
$html .= '</ul>';
|
||||
}
|
||||
|
||||
$html .= '</body></html>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all snapshots.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->snapshots = [];
|
||||
$this->tracker->clear();
|
||||
$this->leakDetector->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset analyzer.
|
||||
*/
|
||||
public function reset(): void
|
||||
{
|
||||
$this->clear();
|
||||
$this->baselineMemory = memory_get_usage(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration.
|
||||
*/
|
||||
public function getConfig(): array
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set configuration.
|
||||
*/
|
||||
public function setConfig(array $config): void
|
||||
{
|
||||
$this->config = array_merge($this->config, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory usage tracker.
|
||||
*/
|
||||
public function getTracker(): MemoryUsageTracker
|
||||
{
|
||||
return $this->tracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory leak detector.
|
||||
*/
|
||||
public function getLeakDetector(): MemoryLeakDetector
|
||||
{
|
||||
return $this->leakDetector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate percentage difference.
|
||||
*/
|
||||
protected function calculatePercentageDiff(int $from, int $to): float
|
||||
{
|
||||
if ($from === 0) {
|
||||
return $to > 0 ? 100 : 0;
|
||||
}
|
||||
|
||||
return (($to - $from) / $from) * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate memory efficiency.
|
||||
*/
|
||||
protected function calculateMemoryEfficiency(): float
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
$totalMemory = array_sum(array_map(fn($s) => $s->getMemoryUsage(), $this->snapshots));
|
||||
$avgMemory = $totalMemory / count($this->snapshots);
|
||||
$peakMemory = memory_get_peak_usage(true);
|
||||
|
||||
if ($peakMemory === 0) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
return ($avgMemory / $peakMemory) * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate memory recommendations.
|
||||
*/
|
||||
protected function generateRecommendations(): array
|
||||
{
|
||||
$recommendations = [];
|
||||
$stats = $this->getStatistics();
|
||||
|
||||
// Check for memory growth
|
||||
if ($stats['growth'] > $this->config['growth_threshold']) {
|
||||
$recommendations[] = [
|
||||
'type' => 'memory',
|
||||
'severity' => 'warning',
|
||||
'message' => sprintf(
|
||||
'High memory growth detected: %s (%.1f%%)',
|
||||
$this->formatBytes($stats['growth']),
|
||||
$stats['growth_percent']
|
||||
),
|
||||
'suggestion' => 'Review memory allocation patterns and consider optimization'
|
||||
];
|
||||
}
|
||||
|
||||
// Check for memory leaks
|
||||
if ($stats['leak_detected']) {
|
||||
$recommendations[] = [
|
||||
'type' => 'leak',
|
||||
'severity' => 'error',
|
||||
'message' => 'Memory leaks detected',
|
||||
'suggestion' => 'Investigate object references and ensure proper cleanup'
|
||||
];
|
||||
}
|
||||
|
||||
// Check memory efficiency
|
||||
if ($stats['memory_efficiency'] < $this->config['efficiency_threshold']) {
|
||||
$recommendations[] = [
|
||||
'type' => 'efficiency',
|
||||
'severity' => 'info',
|
||||
'message' => sprintf(
|
||||
'Low memory efficiency: %.1f%%',
|
||||
$stats['memory_efficiency']
|
||||
),
|
||||
'suggestion' => 'Consider memory optimization techniques'
|
||||
];
|
||||
}
|
||||
|
||||
// Check peak memory usage
|
||||
if ($stats['peak'] > $this->config['peak_threshold']) {
|
||||
$recommendations[] = [
|
||||
'type' => 'peak',
|
||||
'severity' => 'warning',
|
||||
'message' => sprintf(
|
||||
'High peak memory usage: %s',
|
||||
$this->formatBytes($stats['peak'])
|
||||
),
|
||||
'suggestion' => 'Monitor memory usage patterns and optimize peak consumption'
|
||||
];
|
||||
}
|
||||
|
||||
return $recommendations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default configuration.
|
||||
*/
|
||||
protected function getDefaultConfig(): array
|
||||
{
|
||||
return [
|
||||
'growth_threshold' => 50 * 1024 * 1024, // 50MB
|
||||
'peak_threshold' => 100 * 1024 * 1024, // 100MB
|
||||
'efficiency_threshold' => 70, // 70%
|
||||
'auto_snapshot' => true,
|
||||
'snapshot_interval' => 1000, // ms
|
||||
'max_snapshots' => 100,
|
||||
'track_objects' => true,
|
||||
'track_types' => true,
|
||||
'detect_leaks' => true
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human readable format.
|
||||
*/
|
||||
protected function formatBytes(int $bytes): string
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
$bytes /= (1 << (10 * $pow));
|
||||
|
||||
return round($bytes, 2) . ' ' . $units[$pow];
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitor memory usage continuously.
|
||||
*/
|
||||
public function startMonitoring(): void
|
||||
{
|
||||
if (!$this->enabled || !$this->config['auto_snapshot']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$interval = $this->config['snapshot_interval'] * 1000; // Convert to microseconds
|
||||
|
||||
while ($this->enabled) {
|
||||
$this->snapshot('auto_' . time());
|
||||
usleep($interval);
|
||||
|
||||
// Limit number of snapshots
|
||||
if (count($this->snapshots) > $this->config['max_snapshots']) {
|
||||
array_shift($this->snapshots);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory heatmap data.
|
||||
*/
|
||||
public function getHeatmap(): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$heatmap = [];
|
||||
$maxMemory = max(array_map(fn($s) => $s->getMemoryUsage(), $this->snapshots));
|
||||
|
||||
foreach ($this->snapshots as $name => $snapshot) {
|
||||
$memory = $snapshot->getMemoryUsage();
|
||||
$intensity = $maxMemory > 0 ? ($memory / $maxMemory) : 0;
|
||||
|
||||
$heatmap[] = [
|
||||
'name' => $name,
|
||||
'timestamp' => $snapshot->getTimestamp(),
|
||||
'memory' => $memory,
|
||||
'intensity' => $intensity,
|
||||
'color' => $this->getHeatmapColor($intensity)
|
||||
];
|
||||
}
|
||||
|
||||
return $heatmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get heatmap color based on intensity.
|
||||
*/
|
||||
protected function getHeatmapColor(float $intensity): string
|
||||
{
|
||||
if ($intensity < 0.3) {
|
||||
return '#27ae60'; // Green
|
||||
} elseif ($intensity < 0.7) {
|
||||
return '#f39c12'; // Orange
|
||||
} else {
|
||||
return '#e74c3c'; // Red
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze memory patterns.
|
||||
*/
|
||||
public function analyzePatterns(): array
|
||||
{
|
||||
if (empty($this->snapshots)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$patterns = [];
|
||||
$memoryUsages = array_map(fn($s) => $s->getMemoryUsage(), $this->snapshots);
|
||||
|
||||
// Detect growth pattern
|
||||
$isGrowing = $memoryUsages[count($memoryUsages) - 1] > $memoryUsages[0];
|
||||
$patterns['growth_trend'] = $isGrowing ? 'increasing' : 'stable';
|
||||
|
||||
// Detect volatility
|
||||
$avg = array_sum($memoryUsages) / count($memoryUsages);
|
||||
$variance = array_sum(array_map(fn($m) => pow($m - $avg, 2), $memoryUsages)) / count($memoryUsages);
|
||||
$stdDev = sqrt($variance);
|
||||
$patterns['volatility'] = $stdDev / $avg; // Coefficient of variation
|
||||
|
||||
// Detect spikes
|
||||
$spikes = [];
|
||||
for ($i = 1; $i < count($memoryUsages) - 1; $i++) {
|
||||
$prev = $memoryUsages[$i - 1];
|
||||
$current = $memoryUsages[$i];
|
||||
$next = $memoryUsages[$i + 1];
|
||||
|
||||
if ($current > $prev && $current > $next && $current > $avg + $stdDev) {
|
||||
$spikes[] = [
|
||||
'index' => $i,
|
||||
'memory' => $current,
|
||||
'timestamp' => $this->snapshots[$i]->getTimestamp()
|
||||
];
|
||||
}
|
||||
}
|
||||
$patterns['spikes'] = $spikes;
|
||||
|
||||
return $patterns;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user