الأمان والأداء

مراقبة الأداء في الإنتاج

20 دقيقة الدرس 29 من 35

مراقبة الأداء في الإنتاج

تساعد مراقبة أداء الإنتاج في تحديد الاختناقات وتتبع تجربة المستخدم ومنع تراجع الأداء قبل أن يؤثر على المستخدمين.

مراقبة المستخدم الحقيقي (RUM)

قياس تجربة المستخدم الفعلية باستخدام RUM:

<!-- تضمين نص RUM في التخطيط -->
<script>
(function() {
// قياس أداء تحميل الصفحة
window.addEventListener('load', function() {
if (window.performance && window.performance.timing) {
var timing = window.performance.timing;
var loadTime = timing.loadEventEnd - timing.navigationStart;
var domReady = timing.domContentLoadedEventEnd - timing.navigationStart;
var ttfb = timing.responseStart - timing.requestStart;

// إرسال المقاييس إلى الواجهة الخلفية
fetch('/api/rum-metrics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
page: window.location.pathname,
load_time: loadTime,
dom_ready: domReady,
ttfb: ttfb,
user_agent: navigator.userAgent,
connection: navigator.connection?.effectiveType,
})
});
}
});
})();
</script>
مقاييس RUM الرئيسية:
  • TTFB: الوقت حتى البايت الأول (وقت استجابة الخادم)
  • FCP: أول رسم للمحتوى (أول محتوى مرئي)
  • LCP: أكبر رسم للمحتوى (المحتوى الرئيسي مرئي)
  • FID: أول تأخير في الإدخال (التفاعلية)
  • CLS: التحول التراكمي في التخطيط (الاستقرار البصري)

تتبع مؤشرات الويب الأساسية

مراقبة مؤشرات الويب الأساسية من Google:

<script>
// استخدام مكتبة web-vitals
import {getCLS, getFID, getFCP, getLCP, getTTFB} from 'web-vitals';

function sendToAnalytics(metric) {
// إرسال إلى نقطة نهاية التحليلات الخاصة بك
fetch('/api/web-vitals', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
delta: metric.delta,
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
})
});
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
</script>

تتبع أداء الواجهة الخلفية

وسيط Laravel لتتبع أداء الطلب:

// app/Http/Middleware/PerformanceMonitoring.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

class PerformanceMonitoring
{
public function handle($request, Closure $next)
{
$startTime = microtime(true);
$startMemory = memory_get_usage();

// معالجة الطلب
$response = $next($request);

// حساب المقاييس
$duration = (microtime(true) - $startTime) * 1000; // ms
$memoryUsed = memory_get_usage() - $startMemory;
$queryCount = count(DB::getQueryLog());

// تسجيل الطلبات البطيئة
if ($duration > 1000) { // > 1 ثانية
Log::warning('تم اكتشاف طلب بطيء', [
'url' => $request->fullUrl(),
'method' => $request->method(),
'duration_ms' => $duration,
'memory_mb' => round($memoryUsed / 1024 / 1024, 2),
'query_count' => $queryCount,
]);
}

// إضافة رؤوس الأداء
$response->header('X-Response-Time', round($duration, 2) . 'ms');
$response->header('X-Query-Count', $queryCount);

return $response;
}
}

المراقبة الاصطناعية

اختبار آلي من مواقع متعددة:

// استخدام Pingdom API أو خدمة مماثلة
// config/monitoring.php
return [
'synthetic_checks' => [
[
'name' => 'وقت تحميل الصفحة الرئيسية',
'url' => 'https://example.com',
'frequency' => 60, // ثواني
'locations' => ['US-East', 'EU-West', 'Asia-Pacific'],
'threshold_ms' => 2000,
],
[
'name' => 'فحص صحة API',
'url' => 'https://api.example.com/health',
'frequency' => 30,
'expected_status' => 200,
],
],
];

// نص مراقبة اصطناعي مخصص
// app/Console/Commands/SyntheticMonitoring.php
class SyntheticMonitoring extends Command
{
public function handle()
{
$checks = config('monitoring.synthetic_checks');

foreach ($checks as $check) {
$start = microtime(true);
$response = Http::timeout(10)->get($check['url']);
$duration = (microtime(true) - $start) * 1000;

if ($duration > $check['threshold_ms']) {
$this->alert('تم تجاوز عتبة الأداء', [
'check' => $check['name'],
'duration' => $duration,
]);
}
}
}
}

كشف تراجع الأداء

اكتشاف تدهور الأداء بمرور الوقت:

// تخزين مقاييس الأداء الأساسية
// database/migrations/xxxx_create_performance_baselines.php
Schema::create('performance_baselines', function (Blueprint $table) {
$table->id();
$table->string('endpoint');
$table->decimal('p50_ms', 8, 2); // متوسط وقت الاستجابة
$table->decimal('p95_ms', 8, 2); // المئين 95
$table->decimal('p99_ms', 8, 2); // المئين 99
$table->integer('sample_size');
$table->timestamp('measured_at');
});

// خوارزمية كشف التراجع
class PerformanceRegressionDetector
{
public function detectRegression(string $endpoint, float $currentP95): bool
{
$baseline = PerformanceBaseline::where('endpoint', $endpoint)
->latest('measured_at')
->first();

if (!$baseline) {
return false;
}

// تنبيه إذا كان p95 الحالي أسوأ بنسبة 50% من الأساس
$threshold = $baseline->p95_ms * 1.5;

if ($currentP95 > $threshold) {
$this->sendAlert([
'endpoint' => $endpoint,
'baseline_p95' => $baseline->p95_ms,
'current_p95' => $currentP95,
'degradation_percent' => (($currentP95 / $baseline->p95_ms) - 1) * 100,
]);

return true;
}

return false;
}
}
مزالق شائعة: لا تراقب المتوسطات فقط (استخدم المئينات)، تجنب تحيز العينة، راقب خلال ساعات الذروة، وضع في الاعتبار الاختلافات الجغرافية.

اختبار أداء A/B

مقارنة الأداء بين المتغيرات:

// وسيط لتتبع أداء المتغير
class ABTestPerformance
{
public function handle($request, Closure $next)
{
$variant = $request->cookie('ab_variant', 'control');
$startTime = microtime(true);

$response = $next($request);

$duration = (microtime(true) - $startTime) * 1000;

// تسجيل الأداء حسب المتغير
DB::table('ab_performance')->insert([
'variant' => $variant,
'endpoint' => $request->path(),
'duration_ms' => $duration,
'created_at' => now(),
]);

return $response;
}
}

// تحليل أداء المتغير
$analysis = DB::table('ab_performance')
->select(
'variant',
DB::raw('AVG(duration_ms) as avg_duration'),
DB::raw('PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_ms) as p95')
)
->where('created_at', '>', now()->subDays(7))
->groupBy('variant')
->get();

أداء استعلام قاعدة البيانات

تتبع الاستعلامات البطيئة في الإنتاج:

// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

public function boot()
{
DB::listen(function ($query) {
if ($query->time > 1000) { // > 1 ثانية
Log::warning('تم اكتشاف استعلام بطيء', [
'sql' => $query->sql,
'bindings' => $query->bindings,
'time_ms' => $query->time,
]);
}
});
}

ميزانيات الأداء من جانب العميل

فرض ميزانيات الأداء في CI/CD:

// performance-budget.json
{
"budgets": [
{
"resourceType": "script",
"budget": 300 // KB
},
{
"resourceType": "stylesheet",
"budget": 50
},
{
"resourceType": "image",
"budget": 500
},
{
"metric": "interactive",
"budget": 3000 // ms
},
{
"metric": "first-contentful-paint",
"budget": 1500
}
]
}

# استخدام Lighthouse CI في خط الأنابيب
npm install -g @lhci/cli
lhci autorun --config=lighthouserc.json
أفضل الممارسات: حدد ميزانيات الأداء مبكراً، تتبع الاتجاهات بمرور الوقت، راقب المئينات (p50، p95، p99)، وربط الأداء بمقاييس الأعمال (التحويل، معدل الارتداد).
تمرين: نفذ تتبع RUM للصفحات الرئيسية لتطبيقك. قس مؤشرات الويب الأساسية لمدة أسبوع واحد. حدد أبطأ 5% من الطلبات وحقق في الأسباب الجذرية. حدد خط أساس الأداء لنقاط النهاية الحرجة.