انتقل إلى المحتوى الرئيسي

السجلات وCloudWatch لـ Lambda

مقدمة​

السجلات ضرورية لفهم سلوك وظائف Lambda الخاصة بك وتشخيص المشاكل. Amazon CloudWatch Logs هو الخدمة الأصلية لجمع وتخزين وتحليل هذه السجلات.

بنية سجلات Lambda​

┌─────────────────────────────────────────────────────────────────┐
│ تدفق سجلات LAMBDA │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Lambda │────►│ CloudWatch │────►│ تحليل │ │
│ │ Function │ │ Logs │ │ / تنبيهات │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ كل استدعاء يولد : │
│ • START RequestId │
│ • سجلاتك (print, console.log) │
│ • END RequestId │
│ • REPORT (المدة، الذاكرة، الفوترة) │
│ │
└─────────────────────────────────────────────────────────────────┘

هيكل مجموعات السجلات​

CloudWatch Logs
│
├── /aws/lambda/ma-fonction-1
│ ├── Log Stream 2024/01/15/[$LATEST]abc123
│ ├── Log Stream 2024/01/15/[$LATEST]def456
│ └── Log Stream 2024/01/16/[$LATEST]ghi789
│
├── /aws/lambda/ma-fonction-2
│ └── ...
│
└── /aws/lambda/ma-fonction-3
└── ...

المفاهيم الأساسية:

  • Log Group : مجموعة لكل وظيفة Lambda (/aws/lambda/nom-fonction)
  • Log Stream : تدفق لكل مثيل من حاوية Lambda
  • Log Event : كل سطر سجل فردي

تنسيق سجلات Lambda​

رسالة START​

START RequestId: 12345-abcde-67890 Version: $LATEST

رسائل مخصصة (الكود الخاص بك)​

# Python
print("معالجة المستخدم:", user_id)
logger.info("الاتصال بقاعدة البيانات")
logger.error("خطأ: الملف غير موجود")
// Node.js
console.log("معالجة المستخدم:", userId);
console.info("الاتصال بقاعدة البيانات");
console.error("خطأ: الملف غير موجود");

رسالة END​

END RequestId: 12345-abcde-67890

رسالة REPORT (مهم جداً!)​

REPORT RequestId: 12345-abcde-67890
Duration: 234.56 ms
Billed Duration: 235 ms
Memory Size: 128 MB
Max Memory Used: 67 MB
Init Duration: 145.23 ms

تحليل REPORT​

┌─────────────────────────────────────────────────────────────────┐
│ تحليل REPORT │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Duration: 234.56 ms │
│ └── وقت التنفيذ الفعلي للكود الخاص بك │
│ │
│ Billed Duration: 235 ms │
│ └── الوقت المفوتر (مقرب لأعلى مللي ثانية) │
│ │
│ Memory Size: 128 MB │
│ └── الذاكرة المخصصة (المكونة) │
│ │
│ Max Memory Used: 67 MB │
│ └── الذاكرة المستخدمة فعلياً │
│ إذا كانت قريبة من Memory Size = خطر OOM! │
│ │
│ Init Duration: 145.23 ms (Cold Start فقط) │
│ └── وقت تهيئة الحاوية │
│ │
└─────────────────────────────────────────────────────────────────┘

أفضل ممارسات التسجيل​

1. بنية التسجيل (JSON)​

import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
# بنية السجل لتسهيل التحليل
log_entry = {
"level": "INFO",
"request_id": context.aws_request_id,
"action": "process_order",
"order_id": event.get("order_id"),
"user_id": event.get("user_id")
}
logger.info(json.dumps(log_entry))

2. مستويات السجل​

┌─────────────────────────────────────────────────────────────────┐
│ مستويات السجل │
├─────────────────────────────────────────────────────────────────┤
│ │
│ DEBUG → تفاصيل تقنية (للمطورين فقط) │
│ INFO → عمليات عادية │
│ WARNING → حالات غير طبيعية ولكنها معالجة │
│ ERROR → أخطاء تحتاج إلى اهتمام │
│ CRITICAL → أخطاء خطيرة، الوظيفة معرضة للخطر │
│ │
│ الإنتاج : INFO وما فوق │
│ التطوير : DEBUG وما فوق │
│ │
└─────────────────────────────────────────────────────────────────┘

3. المعلومات الأساسية للتسجيل​

def lambda_handler(event, context):
# دائماً سجل في البداية
logger.info(f"START - RequestId: {context.aws_request_id}")
logger.info(f"Event: {json.dumps(event)}")

try:
# منطقك
result = process_data(event)

# سجل النجاح
logger.info(f"SUCCESS - Result: {result}")
return result

except Exception as e:
# سجل الخطأ مع التفاصيل
logger.error(f"ERROR - Type: {type(e).__name__}")
logger.error(f"ERROR - Message: {str(e)}")
logger.error(f"ERROR - Event: {json.dumps(event)}")
raise

البحث في السجلات​

CloudWatch Logs Insights​

-- العثور على جميع الأخطاء
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 100

-- تحليل أوقات التنفيذ
fields @timestamp, @duration
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), min(@duration)

-- العثور على Cold Starts
fields @timestamp, @message
| filter @message like /Init Duration/
| sort @timestamp desc

-- الذاكرة القريبة من الحد
fields @timestamp, @maxMemoryUsed, @memorySize
| filter @type = "REPORT"
| filter @maxMemoryUsed / @memorySize > 0.8

فلاتر الأنماط​

# العثور على الأخطاء
?ERROR ?Error ?error

# العثور على RequestId محدد
"12345-abcde-67890"

# العثور على timeouts
"Task timed out"

# العثور على OOM (Out of Memory)
"Runtime exited" "memory"

احتفاظ السجلات​

┌─────────────────────────────────────────────────────────────────┐
│ احتفاظ السجلات │
├─────────────────────────────────────────────────────────────────┤
│ │
│ بشكل افتراضي : يتم الاحتفاظ بالسجلات إلى أجل غير مسمى │
│ └── انتبه لتكاليف التخزين! │
│ │
│ خيارات الاحتفاظ : │
│ • 1 يوم، 3 أيام، 5 أيام، 1 أسبوع │
│ • 2 أسبوع، 1 شهر، 2 شهر، 3 شهر │
│ • 6 شهر، 1 سنة، 13 شهر، 18 شهر │
│ • 2 سنة، 3 سنوات، 5 سنوات، 10 سنوات │
│ • لا تنتهي أبداً │
│ │
│ التوصية : │
│ • Dev/Test : 1-7 أيام │
│ • الإنتاج : 30-90 يوم │
│ • الامتثال : حسب اللوائح │
│ │
└─────────────────────────────────────────────────────────────────┘

المقاييس الهامة​

المقياسالوصفالعتبة النموذجية للتنبيه
Invocationsعدد الاستدعاءاتحسب الخط الأساسي
Durationوقت التنفيذ> 80% من المهلة
Errorsعدد الأخطاء> 1% من الاستدعاءات
Throttlesالاستدعاءات المحدودة> 0
ConcurrentExecutionsالتنفيذ المتوازي> 80% من الحد

تمرين عملي​

السيناريو : تحليل سجلات وظيفة بها مشكلة​

السجلات الملاحظة :
────────────────────────────────────────────────────────
START RequestId: abc-123
Connecting to database...
REPORT Duration: 29543.21 ms Billed: 29544 ms
Memory: 128 MB Max Used: 125 MB

START RequestId: def-456
Connecting to database...
Task timed out after 30.00 seconds

START RequestId: ghi-789
Runtime exited with error: signal: killed
────────────────────────────────────────────────────────

الأسئلة :
1. ما هي المشكلة الرئيسية؟
2. ما هي المقاييس غير الطبيعية؟
3. ما هي الحلول التي تقترحها؟
عرض التحليل

المشاكل المحددة :

  1. Timeout : الوظيفة تستغرق تقريباً 30 ثانية (الحد)
  2. الذاكرة : 125/128 MB مستخدمة (97% - حرج!)
  3. OOM : "Runtime exited... signal: killed" = Out of Memory

الحلول :

  1. زيادة الذاكرة (256 MB أو أكثر)
  2. تحسين كود الاتصال بقاعدة البيانات (connection pooling)
  3. زيادة المهلة إذا لزم الأمر
  4. إضافة سجلات لتحديد عنق الزجاجة

الملخص​

  • CloudWatch Logs تلتقط تلقائياً جميع سجلات Lambda
  • رسالة REPORT تحتوي على مقاييس الأداء
  • استخدم التسجيل الهيكلي (JSON) لتسهيل التحليل
  • قم بتكوين الاحتفاظ للتحكم في التكاليف
  • CloudWatch Logs Insights يسمح باستعلامات SQL على السجلات

القسم التالي : اختبار التحقق