سير العمل لنشر الإنتاج
مراقبة الإنتاج والاستجابة للحوادث
5 دقيقة للقراءة
الملاحظة للكود المُنشأ بالذكاء الاصطناعي
الكود المُنشأ بالذكاء الاصطناعي يتطلب ملاحظة محسنة لـ:
- اكتشاف السلوكيات غير المتوقعة بسرعة
- فهم التفاعلات المعقدة
- تتبع المشاكل عبر النظام
- التعلم من أنماط الإنتاج
الركائز الثلاث للملاحظة
1. التسجيل المنظم
// lib/logger.ts
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label })
},
timestamp: pino.stdTimeFunctions.isoTime,
base: {
service: process.env.SERVICE_NAME,
version: process.env.APP_VERSION,
environment: process.env.NODE_ENV
}
});
// التسجيل السياقي للتتبع
export function createRequestLogger(requestId: string, userId?: string) {
return logger.child({
requestId,
userId,
traceId: getTraceId()
});
}
// الاستخدام في المعالجات
async function handleOrder(req: Request) {
const log = createRequestLogger(req.id, req.user?.id);
log.info({ orderId: order.id }, 'معالجة الطلب');
try {
const result = await processOrder(order);
log.info({ orderId: order.id, result: 'success' }, 'اكتمل الطلب');
return result;
} catch (error) {
log.error({
orderId: order.id,
error: error.message,
stack: error.stack
}, 'فشلت معالجة الطلب');
throw error;
}
}
2. جمع المقاييس
// lib/metrics.ts
import { Counter, Histogram, Registry } from 'prom-client';
const registry = new Registry();
// مقاييس الطلبات
const httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds',
help: 'مدة طلبات HTTP',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5]
});
const httpRequestTotal = new Counter({
name: 'http_requests_total',
help: 'إجمالي طلبات HTTP',
labelNames: ['method', 'route', 'status_code']
});
// مقاييس الأعمال
const ordersProcessed = new Counter({
name: 'orders_processed_total',
help: 'إجمالي الطلبات المعالجة',
labelNames: ['status', 'payment_method']
});
const paymentAmount = new Histogram({
name: 'payment_amount_dollars',
help: 'مبالغ الدفع بالدولار',
labelNames: ['currency'],
buckets: [10, 50, 100, 500, 1000, 5000]
});
registry.registerMetric(httpRequestDuration);
registry.registerMetric(httpRequestTotal);
registry.registerMetric(ordersProcessed);
registry.registerMetric(paymentAmount);
3. التتبع الموزع
// lib/tracing.ts
import { trace, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('my-service');
export async function withTracing<T>(
name: string,
attributes: Record<string, string>,
fn: () => Promise<T>
): Promise<T> {
const span = tracer.startSpan(name, { attributes });
try {
const result = await fn();
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
span.recordException(error);
throw error;
} finally {
span.end();
}
}
// الاستخدام
async function processPayment(orderId: string, amount: number) {
return withTracing(
'process-payment',
{ orderId, amount: String(amount) },
async () => {
// منطق الدفع هنا
}
);
}
المراقبة الخاصة بالذكاء الاصطناعي
اكتشاف الأنماط الشاذة
// monitoring/anomaly-detection.ts
interface MetricWindow {
mean: number;
stdDev: number;
samples: number[];
}
class AnomalyDetector {
private windows: Map<string, MetricWindow> = new Map();
private threshold = 3; // الانحرافات المعيارية
record(metric: string, value: number): void {
const window = this.windows.get(metric) || {
mean: value,
stdDev: 0,
samples: []
};
window.samples.push(value);
if (window.samples.length > 100) {
window.samples.shift();
}
// تحديث الإحصائيات
window.mean = this.mean(window.samples);
window.stdDev = this.stdDev(window.samples, window.mean);
this.windows.set(metric, window);
// التحقق من الشذوذ
const zScore = Math.abs((value - window.mean) / window.stdDev);
if (zScore > this.threshold && window.samples.length > 50) {
this.alertAnomaly(metric, value, zScore);
}
}
private alertAnomaly(metric: string, value: number, zScore: number): void {
logger.warn({
metric,
value,
zScore,
mean: this.windows.get(metric)?.mean
}, 'تم اكتشاف شذوذ');
// إطلاق التنبيه
alertManager.trigger({
severity: 'warning',
title: `شذوذ في ${metric}`,
description: `القيمة ${value} بعيدة ${zScore.toFixed(1)} انحراف معياري عن المتوسط`
});
}
}
إجراءات الاستجابة للحوادث
قالب Runbook
# Runbook الاستجابة للحوادث: معدل أخطاء عالي
## الاكتشاف
- التنبيه: معدل الخطأ > 1% لمدة 5 دقائق
- لوحة التحكم: https://grafana.example.com/errors
- الخدمات المتأثرة: API، الدفع
## تصنيف الخطورة
- P1 (حرج): >5% معدل خطأ، تأثير على المستخدم
- P2 (عالي): 1-5% معدل خطأ، تجربة متدهورة
- P3 (متوسط): <1% معدل خطأ، تأثير محدود
## الإجراءات الفورية
### الخطوة 1: تقييم التأثير
```bash
# تحقق من معدل الخطأ الحالي
curl -s localhost:9090/api/v1/query \
-d 'query=rate(http_requests_total{status=~"5.."}[5m])' | jq
# تحقق من النقاط النهائية المتأثرة
curl -s localhost:9090/api/v1/query \
-d 'query=topk(5, rate(http_requests_total{status=~"5.."}[5m]))'
الخطوة 2: تحقق من النشرات الأخيرة
# اذكر النشرات الأخيرة
kubectl rollout history deployment/api
# تحقق من توقيت النشر مقابل ارتفاع الأخطاء
# إذا كان مرتبطًا، فكر في التراجع
الخطوة 3: تراجع إذا لزم الأمر
# التراجع للإصدار السابق
kubectl rollout undo deployment/api
# تحقق من التراجع
kubectl rollout status deployment/api
الخطوة 4: تحقق من السبب الجذري
# احصل على سجلات الأخطاء
kubectl logs -l app=api --since=30m | grep ERROR
# تحقق من الأنماط
kubectl logs -l app=api --since=30m | grep ERROR | sort | uniq -c | sort -rn
بعد الحادث
- وثق الجدول الزمني في تقرير الحادث
- حدد السبب الجذري
- أنشئ تذاكر للإصلاحات
- جدول post-mortem
### إنشاء الحادث الآلي
```typescript
// incidents/auto-create.ts
interface IncidentData {
title: string;
severity: 'P1' | 'P2' | 'P3';
service: string;
description: string;
runbookUrl: string;
}
async function createIncident(data: IncidentData): Promise<string> {
// إنشاء حادث PagerDuty
const incident = await pagerduty.createIncident({
title: data.title,
service_key: process.env.PD_SERVICE_KEY,
severity: data.severity,
details: {
service: data.service,
description: data.description,
runbook: data.runbookUrl,
dashboard: `https://grafana.example.com/d/${data.service}`
}
});
// إنشاء قناة Slack
const channel = await slack.createChannel(`inc-${incident.id}`);
// نشر السياق الأولي
await slack.postMessage(channel.id, {
blocks: [
{
type: 'header',
text: { type: 'plain_text', text: `🚨 ${data.title}` }
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*الخطورة:* ${data.severity}\n*الخدمة:* ${data.service}\n*Runbook:* ${data.runbookUrl}`
}
}
]
});
return incident.id;
}
التعلم بعد الحادث
Post-Mortem بمساعدة الذكاء الاصطناعي
claude "حلل هذا الحادث وأنشئ post-mortem:
الجدول الزمني:
- 14:23 انطلق التنبيه لمعدل أخطاء عالي
- 14:25 المهندس المناوب أقر
- 14:32 تم تحديد السبب الجذري (null pointer في معالج الدفع)
- 14:35 بدأ التراجع
- 14:38 تعافت الخدمة
أنشئ post-mortem بدون لوم مع:
1. ملخص تنفيذي
2. تقييم التأثير
3. الجدول الزمني
4. تحليل السبب الجذري
5. العوامل المساهمة
6. عناصر العمل لمنع التكرار"
التعلم من الإنتاج
// monitoring/production-learner.ts
// تتبع الأنماط في أخطاء الإنتاج
interface ErrorPattern {
signature: string;
count: number;
firstSeen: Date;
lastSeen: Date;
contexts: object[];
}
async function analyzeProductionPatterns(): Promise<void> {
const errors = await getRecentErrors(24 * 60); // آخر 24 ساعة
const patterns = groupBySignature(errors);
// توليد الرؤى
const prompt = `
حلل أنماط الأخطاء هذه من الإنتاج:
${JSON.stringify(patterns)}
حدد:
1. الأسباب الجذرية الشائعة
2. الأنماط التي تشير إلى مشاكل الكود
3. الأنماط التي تشير إلى مشاكل البنية التحتية
4. توصيات لتحسينات الكود
`;
const insights = await claude.analyze(prompt);
// إنشاء تذاكر للرؤى القابلة للتنفيذ
for (const insight of insights.actionItems) {
await createJiraTicket({
title: insight.title,
description: insight.description,
priority: insight.severity
});
}
}
ملخص الوحدة
لقد تعلمت:
- تكوين خطوط أنابيب CI/CD للكود المُنشأ بالذكاء الاصطناعي
- تنفيذ استراتيجيات النشر الآمن
- مراقبة الحوادث الإنتاجية والاستجابة لها
بعد ذلك، سنستكشف دراسات حالة من العالم الحقيقي للـ vibe coding المتقدم قيد التطبيق. :::