الاستعلام عن السجلات والتحقيق في الأحداث
الاستعلام عن السجلات والتحقيق في الأحداث
معرفة كيفية استيعاب السجلات وتخزينها هي الأساس. أما معرفة كيفية الاستعلام عنها تحت الضغط — خلال حادث نشط في الثالثة صباحًا، حين يسأل المسؤول عما جرى — فهي المهارة التشغيلية التي تفرق بين المهندسين الكبار وسواهم. هذا الدرس غوص عميق في البحث الفعّال عن السجلات: لغات الاستعلام، وسير عمل التصحيح، والعادات التي تنقلك من "ثمة خطأ ما" إلى "تم تحديد السبب الجذري" في دقائق لا ساعات.
لغتا الاستعلام: LogQL و KQL
يحدد اختيارك لمنصة التخزين لغة الاستعلام المستخدمة. تستخدم Loki لغة LogQL، فيما تستخدم Elasticsearch لغة KQL (لغة استعلام Kibana) أو بنية Lucene الكاملة. كلتاهما تتبعان نمطًا مفاهيميًا واحدًا: تضييق نطاق البحث أولًا بمرشحات التسميات/الفهرس، ثم تطبيق مرشحات المحتوى على المجموعة المضيّقة. ترتيب العمليات بالعكس — مسح كل المحتوى قبل التصفية بالتسميات — هو السبب الأكثر شيوعًا للاستعلامات البطيئة على نطاق الإنتاج.
LogQL (Grafana Loki)
يتكون استعلام LogQL من جزأين إلزاميين: محدد البث (مطابقات التسميات بين الأقواس المعقوصة) وخط أنابيب السجل (مراحل مفصولة بأنبوب). يُقيَّم محدد البث مقابل الفهرس — وهو عملية رخيصة. أما مراحل خط الأنابيب فتعمل على بيانات الأجزاء الخام — وهي مكلفة ويجب أن تكون ضيقة قدر الإمكان.
namespace="checkout" قبل env="production". تُقيِّم Loki مطابقات التسميات من اليسار إلى اليمين؛ المطابقة الأولى تُقلّص أكبر عدد من الأجزاء وتجعل كل مرحلة لاحقة أسرع. تسمي فرق SRE في Google هذا النهج "دفع المرشحات نحو التخزين" وهو ينطبق على جميع محركات استعلام السجلات.KQL (Kibana / Elasticsearch)
KQL هي لغة استعلام مبسطة مبنية فوق Lucene. تنسجم بديهيًا مع البحث على مستوى الحقل، والنطاقات، والمنطق البولياني. للمستخدمين المتقدمين، يُضيف بناء Lucene الكامل (يُفعَّل عبر مبدّل في Kibana Discover) المطابقة الضبابية وبحث القرب وأنماط حرف البدل. يُترجَم كلاهما داخليًا إلى استعلامات Elasticsearch DSL.
filter في KQL (مقابل must في DSL) لا تؤثر على درجة الملاءمة وتُخزّنها Elasticsearch في ذاكرة التخزين المؤقت — مما يجعلها أسرع بكثير. فضّل استخدام filter في جميع استعلامات الحقول المنظمة. استخدم must (الذي يحسب الدرجة) فقط عند الحاجة إلى تصنيف ملاءمة النص الكامل، وهو أمر نادر في البحث التشغيلي عن السجلات.سير عمل التصحيح المبني على السجلات
سير عمل التصحيح المنهجي ليس اختياريًا على النطاق الكبير — إنه ما يمنعك من التخبط عشوائيًا عبر السجلات بينما يتصاعد متوسط وقت الاسترداد. تتبع فرق SRE في كبرى الشركات نمطًا ثابتًا بصرف النظر عن منصة التسجيل:
- تحديد النطاق: اضبط النافذة الزمنية على لحظة ما قبيل إطلاق التنبيه. ثبّت تسميات الخدمة ذات الصلة. النوافذ الزمنية الواسعة تضاعف تكلفة الاستعلام — ابدأ ضيقًا وتوسّع فقط عند الحاجة.
- قياس الحجم: شغّل استعلام معدل الأخطاء مجمّعًا عبر الزمن (مثل:
rate({app="checkout"} | json | level="error" [1m])). حدد الدقيقة التي ارتفع فيها معدل الأخطاء بالضبط. هذا يمنعك من إضاعة الوقت في ضوضاء غير ذات صلة في نفس النافذة. - التصفية: انغمس في دقيقة الارتفاع. طبّق مرشحات الكلمات المفتاحية والحقول لعزل فئة الخطأ. اطلع على عدد من سطور السجل الخام — رسالة الخطأ الفعلية أو تتبع المكدس أو المضيف المنبثق موجودة هناك في الغالب.
- الربط: خذ
trace_idأوrequest_idأوuser_idمن أحد سطور السجل الفاشلة. استعلم عنه عبر جميع الخدمات. هذا يُعيد بناء مسار الطلب الكامل ويكشف الخدمة التي أدخلت الخلل فعلًا مقابل الخدمات الضحايا في المصب. - تحديد السبب الجذري: أنشئ الجدول الزمني: متى ظهر أول سجل شاذ؟ ماذا تغيّر (نشر، دفع إعدادات، ارتفاع حركة المرور، انتهاء شهادة)؟ ما هو نطاق التأثير (كم عدد المستخدمين/الطلبات المتأثرة)؟ وثّق ذلك لتقرير ما بعد الحادث.
الربط بين الخدمات عبر معرّفات التتبع
أقوى قدرة في منظومة المراقبة الحديثة هي القفز من سطر سجل إلى التتبع الموزع الكامل والعودة. لا يعمل هذا إلا إذا كان كل سطر سجل من كل خدمة يحمل trace_id يطابق التتبع المسجّل في Tempo أو Jaeger. عمليًا يعني هذا أن إطار عمل تطبيقك (OpenTelemetry SDK، أو Spring Sleuth، إلخ) يجب أن يحقن سياق التتبع النشط في خريطة MDC/السياق الخاصة بالسجل، وأن يُصدر تنسيق السجل المنظم هذا السياق كحقل JSON من المستوى الأعلى.
في Grafana، يمكن تهيئة مصدر بيانات Loki بـحقل مشتق يحوّل كل قيمة trace_id في سطر السجل إلى رابط قابل للنقر يفتح Grafana Tempo عند ذلك التتبع بالضبط. هذا يلغي خطوة النسخ واللصق اليدوية، وهي الطريقة التي تحقق بها الفرق المتميزة متوسط وقت استرداد أقل من خمس دقائق في حالات الإخفاق الموزعة المعقدة.
التنبيه من استعلامات السجلات
استعلام السجل الذي تشغّله يدويًا خلال حادث ما هو نصف القيمة فقط. الاستعلام ذاته، عند تشغيله على جدول زمني، يصبح تنبيهًا استباقيًا يُعلمك قبل أن يرفع أي مستخدم تذكرة. يدعم كل من Grafana وKibana قواعد التنبيه المبنية على السجلات. في Grafana، يمكن لاستعلام LogQL للمقاييس أن يسند قاعدة تنبيه قياسية؛ وفي Kibana، تُقيّم قواعد التنبيه استعلامات KQL/ES|QL على جدول زمني قابل للتهيئة.
for: 3m في قواعد تنبيه Grafana لاشتراط استمرار الحالة قبل الإطلاق. هذا الإعداد الواحد يُزيل الغالبية العظمى من التنبيهات الكاذبة.الأنماط المضادة الشائعة في الاستعلام
هذه هي الأخطاء التي تجعل التحقيقات في الحوادث بطيئة وأنظمة التسجيل مكلفة:
- الاستعلام بدون حد زمني. استعلامات "كل الوقت" في Loki تمسح كل جزء كتب على الإطلاق. دائمًا اضبط نطاقًا زمنيًا في Grafana أو مرّر
start/endصراحةً لواجهة Loki HTTP. - استخدام التعبيرات النمطية حين يكفي مطابقة النص.
|= "error"مسح بايت بسيط؛|~ "err.*r"يستدعي محرك RE2. على غيغابايتات من السجلات يصل الفارق إلى 10-20 ضعفًا في وقت الاستعلام. استخدم التعبيرات النمطية فقط حين يستوجبها النمط حقًا. - تسميات عالية الكاردينالية في Loki. إضافة
user_idأوrequest_idكتسميات بث Loki ينشئ ملايين البثوث ويُنهار أداء الاستعلام. ضع البيانات عالية الكاردينالية في جسم سطر السجل (تُحلَّل بـ| json) لا في مجموعة التسميات. - نسيان التحقق من أخطاء المحلل. حين يحلّل LogQL سطر سجل JSON مشوّهًا، يضبط التسمية
__error__. تضمين| __error__=""في استعلامات المعدل يضمن أنك تحسب أحداثًا حقيقية لا إخفاقات تحليل مُتنكّرة كثغرات في بياناتك.