كيف تراقب سير عمل n8n في الإنتاج وتكتشف الأخطاء مبكراً؟

مرحبا الجميع،
لقد كنت أستخدم n8n في بيئة إنتاجية مؤخرًا وكنت أتساءل كيف يتعامل الآخرون معها في البيئات الحقيقية.
عندما يفشل سير عمل في الإنتاج، ما هي عمليتك الفعلية للكشف والتفاعل معه؟
على سبيل المثال:
هل تعتمد على تنبيهات Slack أو البريد الإلكتروني؟
هل تتحقق يدويًا من سجلات التنفيذ؟
أم أنك عادة ما تكتشف المشكلة فقط بعد أن يبلغ العميل عن مشكلة؟
أحاول أن أفهم كيف يدير الناس هنا فعليًا الموثوقية والمراقبة في الإنتاج، وليس فقط في بيئات الاختبار.
فضولي أيضًا:
ما كان أكثر فشل سير عمل مؤلمًا بالنسبة لك في الإنتاج؟
كم من الوقت استغرق اكتشافه؟
أود أن أسمع خبرات من العالم الحقيقي.
شكرا :raising_hands:

@Samueljesus الطريقة الأصلية في n8n لعدم معرفة العميل بحدوث خطأ هي استخدام Error Workflow. بناء سير عمل واحد يبدأ بعقدة Error Trigger، وربطه بعقدة Slack أو بريد إلكتروني، ثم في إعدادات كل سير عمل، اضبط Error Workflow على ذاك السير. أي تنفيذ فاشل سيطلقه تلقائياً وسيرسل لك إشعاراً باسم سير العمل والخطأ، بدلاً من أن تبحث أنت في سجلات التنفيذ بعد الفوات. هناك شيئان يجب معرفتهما، أنه يعمل فقط على عمليات التشغيل النشطة/الإنتاجية وليس على اختبارات التنفيذ اليدوية، وأنه لن يتقاطع مع خطأ داخل سير العمل نفسه. اضبطه كسير عمل الخطأ الافتراضي لك وكل سير عمل سيكون مشمولاً بضربة واحدة.

شكرًا جزيلًا على الرد، @achamm! تدفق Error Trigger الأصلي مفيد جدًا للأخطاء التقليدية.

لدي استفسار تقني: كيف تتعاملون مع هذا عند دمج عقد الذكاء الاصطناعي (مثل AI Agent)؟ لاحظت أنه في كثير من الأحيان، لتجنب توقف الوكيل بشكل كامل، يتم تكوين ‘Continue on Error’ في الأدوات أو الـ subworkflows المتصلة بالوكيل. عند القيام بذلك، ينتهي التدفق بـ ‘أخضر’ (ناجح) لكن النتيجة النهائية للذكاء الاصطناعي تكون هلوسة أو فارغة أو بصيغة خاطئة. بما أن التدفق لا ‘يفشل’ من الناحية التقنية، فإن Error Trigger لا يكتشف المشكلة.

هل وجدتم طريقة فعالة لمراقبة هذه ‘الأخطاء الصامتة’ في الإنتاج دون الاضطرار إلى مراجعة السجلات يدويًا كل يوم؟

@Samueljesus صحيح، Error Trigger يعمل فقط عند حدوث خطأ فعلي، لذا حول “الأخضر لكن السيء” إلى خطأ فعلي. أضف خطوة تحقق بعد الوكيل، عقدة IF أو Code تتحقق من الحقول الفارغة / المفقودة / المخطط الخاطئ، وعندما تفشل وجهها إلى عقدة Stop و Error. هذا يرمي خطأ فعلي تلتقطه سير العمل Error الموجود لديك، حتى الأخطاء الصامتة تصل إلى نفس مسار التنبيه مثل كل شيء آخر. قم بتحليل المخطط في خطوة منفصلة، وليس مباشرة في Structured Output Parser الخاص بالوكيل، فهو غير مستقر مع الوكلاء. الهلوسة التي لا تزال بشكل صحيح هي الصعبة، تحتاج إلى فحص المحتوى، كلمات مفتاحية متوقعة أو نموذج ثاني يقيم المخرجات.

يغطي نهج خطوة التحقق من achamm حالة فشل الذكاء الاصطناعي الصامت بشكل جيد. هناك طبقة إضافية أضيفها فوقها: نمط نبض القلب (heartbeat) لسير العمل المجدول الحرج - طلب HTTP بسيط في نهاية كل تشغيل يرسل إشارة اختبار إلى خدمة مثل Healthchecks.io أو حتى webhook مخصص. يتحقق مراقب منفصل قائم على الجدول الزمني من عدم وصول الإشارات كل 15 دقيقة ويرسل تنبيه Slack إذا لم تصل واحدة. هذا يكتشف نمط فشل مختلفًا: عندما لا يحتوي سير العمل على خطأ بل يتوقف عن التنفيذ تمامًا (فشل cron، إعادة تشغيل n8n، عملية معلقة)، وهو ما لا يمكن لـ Error Trigger اكتشافه.

شكراً @achamm و @nguyenthieutoan، هذا حقاً مفيد جداً.

يبدو أن هناك في الواقع فئات مختلفة من حالات الفشل في الإنتاج:

• حالات الفشل الحتمية (التي يتم التقاطها بواسطة Error Trigger) • حالات الفشل الصامتة (سير العمل ينجح، لكن المخرجات خاطئة أو غير مكتملة) • عمليات التنفيذ المفقودة (سير العمل لا يعمل على الإطلاق)

أنا فضولي بشأن هذا، خاصة بالنسبة لأولئك الذين يديرون عمليات سير عمل متعددة أو مشاريع عملاء متعددة:

أي من هذه الأنواع من حالات الفشل يميل إلى التسبب في أكبر المشاكل في العالم الحقيقي؟

وعندما تكون مسؤولاً عن العشرات من عمليات سير العمل، كيف تتابع كل شيء دون الحاجة إلى التحقق المستمر من السجلات وسجل التنفيذ والوحدات التحكم؟

أود أن أفهم كيف تتعامل الفرق مع هذا على نطاق واسع.

@Samueljesus الطريقة لعدم مراقبة العشرات هي جعل الأخطاء تأتي إليك بدلاً من أن تسحب السجلات بنفسك، وأدخل جميع الأنواع الثلاثة في قناة Slack واحدة (Error Workflow للفشل الحرج، والتحقق من الصحة→Stop والخطأ للفشل الصامت، ونبض القلب للتشغيلات المفقودة) بحيث يغطي تدفق تنبيه واحد كل شيء. للحصول على نظرة عامة واحدة عبر كل سير عمل، فعّل مقاييس Prometheus في n8n باستخدام N8N_METRICS=true وأشر Grafana إلى نقطة نهاية /metrics، ستحصل على عدادات النجاح/الفشل وأوقات التنفيذ لجميع سير العمل على لوحة تحكم واحدة، بدون البحث في السجلات. من بين الثلاثة، الفشل الصامت هو الأكثر ضررًا لأنه يبدو أخضر، ولا شيء يشير إليه ما لم تكن قد بنيت طبقة التحقق من الصحة تلك.

@achamm شكراً، هذه نقطة مثيرة للاهتمام حقاً.

الأخطاء الصامتة هي في الواقع ما كنت أفكر فيه أكثر من غيره، لأن سير العمل قد يظهر كنجح بينما لا يزال ينتج نتيجة غير مفيدة.

على سبيل المثال، سير عمل توليد العملاء المحتملين الذي يعمل بنجاح لكنه لا يجد أي عملاء، أو سير عمل استخراج البريد الإلكتروني الذي يُرجع بيانات فارغة.

كيف تكتشف هذه الحالات عادة في الإنتاج؟ هل تضيف منطق التحقق داخل كل سير عمل، أم تستخدم بعض أسلوب المراقبة الخارجي؟

@Samueljesus بخصوص “ran but came back empty” أنا أفعلها داخل workflow، مباشرة بعد الخطوة التي يجب أن تُرجع البيانات أضع IF للتحقق من العدد (items == 0، أو الحقل فارغ) وأوجه الفرع الفارغ إلى عقدة Stop and Error، بحيث يصبح فشلاً حقيقياً تنبهك عليه Error Workflow الخاصة بك، نفس المسار كما في التعطل الصعب. هذا لكل تشغيل وفوري، أنت تعرف في اللحظة التي يجد فيها التشغيل 0 leads. ثم أضف backstop خارجي للكشف عن الانجراف البطيء، workflow صغير مجدول يتحقق من النتيجة الفعلية (هل تمت إضافة أي leads في آخر 24 ساعة؟) وينبهك إذا كانت منخفضة بشكل مريب. inline للاكتشاف الفوري، external للاتجاه.

هذا منطقي جداً.

التمييز بين التحقق من الصحة لكل تشغيل ومراقبة الاتجاهات مثير للاهتمام حقاً. يقوم أسلوب IF المضمن + Stop and Error بالتقاط المشاكل على الفور، بينما يساعد سير العمل الخارجي في اكتشاف التدهور التدريجي حتى عندما ينجح كل شيء من الناحية التقنية.

لم أفكر في فصل هاتين الطبقتين بهذه الوضوح. شكراً لك على مشاركة إعدادك معي.

أنا في الواقع أجرّب نموذجًا أوليًا يتصل مباشرة بـ n8n، ويصور سير العمل وأخطاء التنفيذ، وأحد المجالات التي أستكشفها هو كيفية الكشف التلقائي عن الأعطال الصامتة والنتائج غير الطبيعية.

لقد أعطتني هذه النقاشات بعض الأفكار حول الجمع بين مراقبة سير العمل ومراقبة النتائج، وهو ما يبدو أنه المكان الذي تظهر فيه معظم المشاكل الإنتاجية الأكثر صعوبة.

@Samueljesus إليك فحص مضمّن يمكنك استيراده والتعديل عليه، المجموعة تحتل مكان خطوة بيانات لديك (استبدلها بالخطوة الفعلية وأشر الـ IF إلى عددها الفعلي)، إذا عاد العدد 0 سينتقل الـ IF إلى Stop and Error الذي يرمي خطأ حقيقي تلتقطه Workflow الخاص بك للأخطاء، بهذه الطريقة تعرض النتيجة ذات 0 في النهاية كفشل بدلاً من الأخضر:

الفرع الخاطئ (العدد ليس أكبر من 0) هو المصيدة، الفرع الصحيح يستمر فقط. بالنسبة لجانب الاتجاه تشغّل نفس فحص العدد على جدول زمني مقابل وجهتك.

شكراً على مشاركة سير العمل، مفيد جداً. هذا في الواقع بالضبط ما أحاول أتمتته باستخدام النموذج الأولي الذي ذكرته — بحيث لا تضطر طبقة التحقق هذه إلى البناء سير العمل تلو الآخر، بل تعمل تلقائياً عبر جميعها. إذا كنت مهتماً برؤيتها عندما يكون لدي شيء أكثر متانة، سأكون سعيداً بمشاركتها معك.

بالتأكيد! كنت سأبدأ موضوعًا جديدًا تحت “Built with n8n” حيث أن سؤالك قد تم حله أعتقد، وتفضل بوضع علامة على أي من الردود في هذا الموضوع كحل! لكنني سأكون سعيدًا بمساعدتك مع ذلك، فقط للحفاظ على تنظيم المنتدى حيث أنك تبني عليه الآن وستعرضه!

حسناً، هذا منطقي! سأفتح موضوعاً جديداً في قسم ‘Built with n8n’ حين يكون لدي شيء يستحق العرض. شكراً على التنبيه وعلى كل المساعدة في هذا الموضوع — كانت قيّمة جداً.

أهلاً وسهلاً! أنا دائماً سعيد بمساعدتك!

التقسيم الذي ساعدني أكثر كان معاملة “فشل” و"تم التشغيل لكن لم ينتج شيء" و"لم يتم التشغيل على الإطلاق" كثلاث مشاكل مختلفة، لأن إعداد التنبيهات الواحد تقريباً لا يغطي جميعها. سير عمل Error Trigger الذي ينشئه الجميع ينطلق فقط للحالة الأولى. إنه لا يفعل شيئاً بشأن التشغيل الذي انتهى بلون أخضر مع جسم فارغ، وبطبيعة الحال لا يمكن أن ينطلق بشأن تشغيل لم يبدأ أبداً، لأنه لا توجد عملية تنفيذية يمكن إرفاقها بها.

في حالة اللون الأخضر مع الفراغ، فكرة عقدة التحقق أعلاه صحيحة، لكنني سأدفعها خطوة واحدة إلى أبعد من مجرد التحقق من الحقول الفارغة. الكثير من أسوأها ليست فارغة، بل إنها قديمة أو غير كاملة. رمز مميز منتهي الصلاحية يعود برمز 200 مع صفر صفوف يبدو متطابقاً مع “لا شيء جديد اليوم” الحقيقي. لذا فإنني أتحقق من الشكل مقابل ما يبدو عليه التشغيل الصحي، وليس فقط التحقق من الصحة، وأسجل العدد في مكان يمكنني الإشراف عليه لمدة بضعة أيام. إذا سحبت أمس 400 صف وسحبت اليوم 0 بدون خطأ، فهذه هي الإشارة، وليس علامة الاختيار الخضراء.

في حالة عدم التشغيل، نبضات القلب هي الشيء الوحيد الذي ينجح، لأنك تحاول اكتشاف غياب شيء ما. الفخ هو موعد نهائي ثابت. إذا كان المهمة عادة تنتهي حول 8:05 وتنبهت في 8:00 بالضبط، فستنبهك باستمرار. امنحها نافذة سماح بناءً على وقت هبوطها المعتاد، وليس وقتاً محدداً.

وقت الكشف صراحة هو كل اللعبة. الأعطال الصعبة أسمع عنها في دقائق. تلك الصامتة التي اكتشفتها بعد أيام، بعد أن كانت البيانات خاطئة بالفعل في المصب، وهذا هو النوع المكلف.

كنت سأراقب سير عمل الذكاء الاصطناعي بطريقة مختلفة عن سير العمل الحتمي العادي.

نمط الفشل الشائع ليس فقط “فشلت العقدة.” بل هو “انتهى سير العمل بنجاح، لكن مخرجات الذكاء الاصطناعي كانت فارغة أو غير منسقة أو منخفضة الثقة أو عديمة الفائدة من الناحية الدلالية.”

بالنسبة لعقد الذكاء الاصطناعي، كنت سأضيف بوابة التحقق من جودة النتائج بعد خطوة النموذج:

  1. فحص الشكل
    هل المخرجات JSON صحيحة / الحقول المتوقعة / نص غير فارغ؟

  2. الحد الأدنى الدلالي
    هل تحتوي على القرار المطلوب أو التصنيف أو الملخص أو الحقول المستخلصة؟

  3. الثقة / حالة الرجوع
    إذا كانت الثقة غائبة أو منخفضة، فوجّه إلى المراجعة بدلاً من معاملتها على أنها نجاح.

  4. التأكيد في المراحل اللاحقة
    قبل إرسال بريد إلكتروني أو تحديث نظام إدارة علاقات العملاء أو كتابة السجلات، تأكد من الحقول التي تتطلبها العقد اللاحقة.

  5. حدث المراقبة
    سجل معرّف سير العمل وبيان تنفيذ وتسمية عقدة الذكاء الاصطناعي وبصمة الإدخال وشكل المخرجات ونتيجة التحقق وعدد المحاولات والمسار النهائي.

إذن التمييز الرئيسي هو:

  • الفشل التقني: فشل التنفيذ؛
  • الفشل المنطقي: نجح التنفيذ لكن المخرجات لا يجب أن تكون موضع ثقة؛
  • الفشل التجاري: كانت المخرجات صحيحة لكن ليست جيدة بما يكفي للإجراء الذي يتخذه المستخدم.

إذا كانت مراقبتك تراقب فقط التنفيذات الفاشلة، فستفقد الفئة الثانية والثالثة.

النصيحة الموجودة أعلاه حول Error Workflow هي الطبقة الأساسية الصحيحة. الفجوة التي أراها عادةً في الإنتاج هي أن الفرق تتوقف عند “إرسال تنبيه Slack” ولا تزال لا تملك حلقة تشغيلية لما يحدث بعد ذلك.

بالنسبة لسير عمل العميل والوكالة، أفصل عادةً أربع فئات. يجب أن تمر الأعطال الحرجة عبر Error Workflow إلى Slack أو البريد الإلكتروني مع اسم سير العمل وعنوان URL للتنفيذ والعميل أو مساحة العمل والمالك. الأعطال الصامتة تحتاج إلى التحقق الصريح بعد خطوات تتضمن الذكاء الاصطناعي أو API، مثل المخرجات الفارغة أو JSON غير الصحيح أو عدد العناصر المنخفض أو الحقول المفقودة المطلوبة أو فروع continue-on-error التي يجب أن تنشئ مشكلة على أي حال. التشغيلات المفقودة تحتاج إلى فحوصات نبض القلب لسير العمل التي يجب أن تعمل وفقاً لجدول زمني، لذلك يتم التقاط “لم يحدث شيء”. إعداد التقارير للعميل يتطلب أن تصبح كل حادثة مشكلة مع الحالة والسبب الجذري والحل وما إذا كان العميل بحاجة إلى معرفة ذلك.

هذا الجزء الأخير هو ما أعمل عليه مع Maintain Flow. وهو موجه للوكالات التي تحافظ على أتمتة العميل بعد الإطلاق: الفحوصات وتشغيل الفحوصات والمشاكل والحلول والتقارير الجاهزة للعميل. حتى لو لم تستخدم أداة منفصلة، فأنا أوصي ببناء نفس الحلقة في مكان ما، وإلا فإن التنبيهات تتراكم لكن لا أحد يستطيع إثبات ما تم إصلاحه.

—موضوع رائع. التقسيم الذي ساعدني أكثر هو نفسه الذي ذكره عدد منكم: الأخطاء الحادة (يمسكها Error Trigger)، والأخطاء الصامتة (تعمل بنجاح لكن المخرجات فارغة أو مشوهة)، والتشغيلات المفقودة (لم تعمل على الإطلاق). لا يغطي إعداد التنبيه الواحد جميع الحالات الثلاث، ووقت الكشف مختلف جداً لكل منها.

بالنسبة لطبقة الأخطاء الحادة، الشيء الذي جعلها منخفضة الصيانة لي هو جعل التنبيه مكتفياً بذاته حتى لا أضطر أبداً إلى البحث. مجموعة Error Workflow واحدة مضبوطة كالافتراضية للمثيل (Settings → Error Workflow)، Error Trigger → عقدة Code صغيرة تسطح الحمول → عقدة HTTP إلى Slack أو Telegram. عقدة Code هي الجزء المهم؛ استخرج الحقول التي تريدها فعلاً في الإشعار:

const e = $input.first().json;
const ex = e.execution || {};
return [{ json: {
  workflow: ex.workflow?.name || 'Unknown',
  node: ex.lastNodeExecuted || 'unknown',
  message: e.execution?.error?.message || e.message || 'Unknown error',
  execution_id: String(ex.id || ''),
  // swap in your n8n base URL (or read it from an env var) so the alert is clickable
  url: `https://your-n8n.example/workflow/${ex.workflow?.id}/executions/${ex.id}`
}}];

ثم تنشر عقدة Slack/Telegram سطراً واحداً يتضمن اسم سير العمل والعقدة الفاشلة والرسالة وURL التشغيل، بحيث يربط التنبيه مباشرة بالتشغيل.
Slack ما هو إلا POST لـ {“text”: “…”} إلى webhook وارد؛
Telegram ما هو إلا POST إلى api.telegram.org/bot/sendMessage.

اضبطه كسير العمل الافتراضي للأخطاء مرة واحدة وكل سير عمل سيكون مغطى.

بالنسبة للفئتين الأخريين أفعل ما قيل هنا بالفعل: IF مضمن (عدد العناصر 0 / الحقل المطلوب فارغ) → Stop and Error بعد خطوة البيانات، بحيث يصبح التشغيل الصامت أو الفارغ فشلاً حقيقياً يمسكه نفس Error Workflow ويوجهه إلى نفس القناة. وضربة قلب (Healthchecks أو ping مجدول) للتشغيلات التي لم تعمل أبداً، لأنه لا يوجد تشغيل لـ Error Trigger للتعلق به. أتفق مع التعليقات أن الأخطاء الصامتة هي التكلفة العالية؛ تبدو خضراء وتكتشفها فقط في اتجاه المصب.

الخلاصة بالنسبة لي: قناة واحدة، جميع أنواع الأخطاء الثلاثة موجهة إليها، كل تنبيه يحمل ما يكفي للتصرف بناءً عليه دون فتح n8n.