تسجيل الدخول إلى تطبيق php الموزع


سوف يناقش المقال فوائد التسجيل. سأقول عن سجلات على PSR. سأضيف بعض التوصيات الشخصية حول العمل مع مستوى ورسالة وسياق الحدث المسجل. سيتم تقديم مثال على كيفية تنظيم التسجيل والمراقبة باستخدام ELK في تطبيق مكتوب بلغة Laravel وتم إطلاقه عبر Docker في عدة حالات. سأوقع قاعدة مهمة لنظام الإنذار. سأقدم مثالاً على برنامج نصي يرفع مكدس المراقبة بالكامل باستخدام أمر واحد.


فوائد قطع الأشجار


يسمح التسجيل الجيد التنظيم بما يلي على الأقل:


  • لمعرفة أن شيئًا ما لا يتم بالشكل المقصود (توجد أخطاء)
  • معرفة تفاصيل الخطأ ، والتي سوف تساعد على تحديد مع من وأين وقع الخطأ ، ومنع تكرار
  • لمعرفة أن كل شيء يسير وفقًا لما هو مخطط له (access.log ، debug- ، info-levels)

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


ما يكتب وما يكتب


قام جزء من مجتمع php بتطوير توصيات لبعض مهام كتابة التعليمات البرمجية. إحدى هذه التوصيات هي واجهة تسجيل PSR-3 . إنها تصف فقط ما تحتاجه لتسجيل الدخول. لهذا ، تم Psr\Log\LoggerInterface الخاصة بحزمة "psr / log". عند استخدامه ، تحتاج إلى معرفة المكونات الثلاثة للحدث:


  1. مستوى - أهمية الحدث
  2. رسالة - نص يصف الحدث
  3. السياق - مجموعة من المعلومات الإضافية حول الحدث

PSR-3 مستويات الحدث


يتم استعارة المستويات من RFC 5424 - Syslog Protocol ، وصفها التقريبي كما يلي:


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

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


  • الطوارئ هي مستوى الأنظمة الخارجية التي يمكنها النظر إلى نظامك وتحديد ما إذا كان لا يعمل تمامًا أو أن التشخيص الذاتي لا يعمل.
  • في حالة تأهب - يمكن للنظام نفسه تشخيص حالته ، على سبيل المثال ، من خلال مهمة مجدولة ، ونتيجة لذلك سجل حدثًا بهذا المستوى. يمكن أن يكون التحقق من الموارد المتصلة أو شيء محدد ، على سبيل المثال ، رصيد في حساب مورد خارجي يستخدم.
  • حرجة - حدث عندما يعطي الفشل مكون نظام مهم للغاية ويجب أن يعمل دائمًا. يعتمد بالفعل كثيرا على ما يفعله النظام. مناسبة للأحداث المهمة التي يجب اكتشافها بسرعة ، حتى لو حدث مرة واحدة فقط.
  • خطأ - حدث حدث حوله ، عند التكرار قريبًا ، تحتاج إلى الإبلاغ. أخفق إكمال الإجراء ، الذي يجب تنفيذه ، لكن هذا الإجراء لا يندرج تحت وصف الحرج. على سبيل المثال ، لم يكن من الممكن حفظ صورة الملف الشخصي للمستخدم بناءً على طلبه ، لكن النظام ليس خدمة لصورة الملف الشخصي ، بل هو نظام دردشة.
  • تحذير - أحداث ، للإبلاغ الفوري عنها ، تحتاج إلى طلب عدد كبير منها خلال فترة زمنية. فشل في تنفيذ إجراء ، والذي لا يكسر الفشل أي شيء خطير. لا تزال هذه الأخطاء ، لكن تصحيحها قد ينتظر جدول العمل. على سبيل المثال ، لم يكن من الممكن حفظ الصورة الرمزية للمستخدم ، وكان النظام متجرًا على الإنترنت. يعد الإخطار عنها ضروريًا (بتردد عالي) للتعرف على الحالات الشاذة المفاجئة ، لأنها يمكن أن تكون أعراض لمشاكل أكثر خطورة.
  • إشعار - هذه هي الأحداث التي تبلغ عن الانحرافات التي يوفرها النظام والتي تعد جزءًا من الأداء الطبيعي للنظام. على سبيل المثال ، حدد المستخدم كلمة المرور الخاطئة عند المدخل ، ولم يملأ المستخدم الاسم الأوسط ، ولكن ليس من الضروري ، قام المستخدم بشراء طلب الحصول على 0 روبل ، ولكن يتم توفير ذلك لك في حالات نادرة. من الضروري أيضًا الإبلاغ عنها بتردد عالٍ ، نظرًا لأن الزيادة الحادة في عدد الانحرافات يمكن أن تكون نتيجة لخطأ يلزم إصلاحه بشكل عاجل.
  • معلومات - الأحداث ، التي تحدث عن الأداء الطبيعي للنظام. على سبيل المثال ، قام مستخدم بالتسجيل أو قام مستخدم بشراء منتج أو ترك مستخدم ملاحظات. يجب تهيئة الإشعار لمثل هذه الأحداث بالطريقة المعاكسة: إذا حدث عدد غير كاف من هذه الأحداث على مدار فترة من الزمن ، فأنت بحاجة إلى الإخطار ، لأن انخفاضها قد يكون سببًا لحدوث خطأ.
  • debug - أحداث لتصحيح العملية على النظام. عند إضافة بيانات كافية إلى سياق الحدث ، يمكنك تشخيص المشكلة ، أو استنتاج أن العملية تعمل بشكل صحيح في النظام. على سبيل المثال ، فتح المستخدم صفحة منتج وتلقى قائمة بالتوصيات. يزيد بشكل كبير من عدد الأحداث المرسلة ، لذلك يجوز إزالة تسجيل هذه الأحداث بعد فترة من الوقت. نتيجة لذلك ، سيكون عدد مثل هذه الأحداث في التشغيل العادي متغيرًا ، ومن ثم يمكن حذف المراقبة للإعلام عنها.

رسالة الحدث


بواسطة PSR-3 ، يجب أن تكون الرسالة عبارة عن سلسلة أو كائن باستخدام الأسلوب __toString() . بالإضافة إلى ذلك ، وفقًا لـ PSR-3 ، قد يحتوي سطر الرسالة على عناصر نائبة للنموذج ”User {username} created” ، والذي يمكن استبداله بقيم من صفيف السياق. عند استخدام Elasticsearch و Kibana للمراقبة ، أوصي بعدم استخدام العناصر النائبة ، ولكن كتابة خطوط ثابتة ، لأن هذا سيؤدي إلى تبسيط تصفية الأحداث ، وسيكون السياق دائمًا هناك. بالإضافة إلى ذلك ، أقترح الانتباه إلى المتطلبات الإضافية للرسالة:


  1. يجب أن يكون النص قصيرًا ولكنه ذو معنى. هذا هو ما سيأتي في التنبيهات ، وما سيكون في قوائم الأحداث التي حدثت.
  2. من الأفضل أن يكون النص فريدًا بالنسبة لأجزاء مختلفة من البرنامج. سيمكن هذا من التنبيه ، دون النظر إلى السياق ، لفهم الجزء الذي وقع فيه الحدث.

سياق الحدث


سياق الحدث لـ PSR-3 عبارة عن صفيف (ربما متداخل) من القيم المتغيرة ، على سبيل المثال ، معرفات الكيانات. يمكن ترك السياق فارغًا إذا كانت الرسالة واضحة حول الحدث. في حالة تسجيل استثناء ، يجب عليك تمرير الاستثناء بأكمله ، وليس فقط getMessage() . عند استخدام Monolog عبر NormalizerFormatter ، سيتم استخراج البيانات المفيدة تلقائيًا من الاستثناء وإضافتها إلى سياق الحدث ، بما في ذلك تتبع المكدس. هذا هو ، تحتاج بدلا من ذلك


 [ 'exception' => $exception->getMessage(), ] 

للاستخدام


 [ 'exception' => $exception, ] 

في Laravel ، يمكنك إدخال بيانات الأحداث في الأحداث تلقائيًا. يمكن القيام بذلك من خلال سياق السجل العام (فقط للاستثناءات غير الناجحة أو من خلال report() ) ، أو من خلال LogFormatter (لجميع الأحداث). عادة ، يتم إضافة المعلومات مع معرف المستخدم الحالي ، وطلب URI ، IP ، طلب UUID وما شابه.


عند استخدام Elasticsearch كمستودع لسجل ، تذكر أنه يستخدم أنواع البيانات الثابتة. أي إذا مررت customer_id في سياق رقم ، فعندما تحاول حفظ حدث بنوع مختلف ، على سبيل المثال ، سلسلة (معرف مستخدم) ، لن تتم كتابة هذه الرسالة. يتم إصلاح أنواع الفهرس عند استلام القيمة لأول مرة. إذا تم إنشاء فهارس كل يوم ، فسيتم تسجيل النوع الجديد فقط في اليوم التالي. ولكن حتى هذا لن يحل جميع المشكلات ، لأن الأنواع من Kibana سيتم خلطها وأن جزءًا من العمليات المرتبطة بالنوع لن يكون متاحًا بينما ستكون هناك فهارس مختلطة.


لمنع هذه المشكلة ، أوصي باتباع القواعد:


  • لا تستخدم أسماء مفاتيح عامة للغاية ، والتي يمكن أن تكون من أنواع مختلفة
  • قم بالاختيار الواضح لنوع القيمة إذا لم تكن متأكدًا من نوعه

مثال: بدلا من ذلك


 [ 'response' => $response->all(), 'customer_id' => $id, 'value' => $someValue, ] 

للاستخدام


 [ 'smsc_response_data' => json_encode($response->all()), 'customer_id' => (string) $customer_id, 'smsc_request_some_value' => (string) $someValue, ] 

استدعاء مسجل من رمز


لتسجيل حدث بسرعة في السجل ، يمكنك الخروج بالعديد من الخيارات. دعونا نفكر في بعضهم.


  1. قم بتعريف log() الوظائف العام log() واتصل به من أجزاء مختلفة من البرنامج. هذا النهج له العديد من العيوب. على سبيل المثال ، في الفصول التي نصل فيها إلى هذه الوظيفة ، يتم تكوين تبعية ضمنية. هذا ينبغي تجنبه. بالإضافة إلى ذلك ، من الصعب تكوين مثل هذا المسجل عندما يحتاج النظام إلى العديد من الأنواع المختلفة. عيب آخر ، إذا كنا نتحدث عن العمل مع Laravel ، هو أننا لا نستخدم الميزات التي يوفرها الإطار لحل هذه المشكلة.
  2. استخدم Laravel facade \ Log. مع هذا النهج ، تبدأ أجزاء النظام التي تصل إلى هذه الواجهة في الاعتماد على الإطار. في أجزاء النظام التي لن نقوم بإزالتها من الإطار ، مثل هذا الحل مناسب تمامًا. على سبيل المثال ، اكتب من بعض مثيلات أمر وحدة التحكم ، مهمة الخلفية ، وحدة التحكم. أو عندما يكون هناك بالفعل هيكل معقد من الخدمات ، وإلقاء مثيل من المسجل فيها ليست بهذه البساطة.
  3. حل تبعية المسجل من خلال مساعدي app() resolve() الإطار. يحتوي النهج على نفس عيوب استخدام الواجهة ، ولكن عليك كتابة رمز أكثر قليلاً.
  4. حدد التبعية على المسجل في مُنشئ الفئة التي سيستخدمها هذا المسجل. في الوقت نفسه ، يجب تحديد نفس LoggerInterface كنوع من أجل الامتثال DIP . بفضل إطارات autowiring ، سيتم حل التبعيات تلقائيًا في تنفيذ التجريدات المعلنة. في Laravel ، يمكن تحديد بعض فئات التبعية بطريقة منفصلة ، بدلاً من تحديدها في مُنشئ الفصل بأكمله.

حيث في الرمز لاستدعاء المسجل


عند تنظيم الكود في المشروع ، قد ينشأ السؤال في أي فئة يجب أن أكتب إلى السجل. هل يجب أن تكون خدمة؟ أو يجب أن يتم ذلك حيث يتم استدعاء الخدمة من: وحدة تحكم ، مهمة خلفية ، أمر وحدة التحكم؟ أو هل يجب أن يقرر كل استثناء ما يكتب إلى السجل باستخدام طريقة report (Laravel) الخاصة به؟ لا توجد إجابة بسيطة على جميع الأسئلة في وقت واحد.


النظر في الفرصة التي قدمها Laravel لتفويض إلى فئة الاستثناء مهمة تسجيل نفسها. لا يمكن أن يعرف الاستثناء مدى أهمية النظام في تحديد مستوى الحدث. بالإضافة إلى ذلك ، لا يتمتع الاستثناء بالوصول إلى السياق ما لم تتم إضافته على وجه التحديد عند استدعاء هذا الاستثناء. للاتصال بأسلوب render على سبيل الاستثناء ، يجب عليك إما عدم الاستثناء (سيتم استخدام ErrorHandler العمومي) ، أو استخدام المساعد العمومي report() واستخدامه. تسمح لنا هذه الطريقة بعدم استدعاء مسجل PSR-3 في كل مرة يمكننا فيها الاستيلاء على هذا الاستثناء. لكنني لا أعتقد أن الأمر يستحق إعطاء الاستثناء من هذه المسؤولية.


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


مثال يوضح استخدام التبعية والسياق الناجح:


 <?php namespace App\Console\Commands; use App\Services\ExampleService; use Illuminate\Console\Command; use Psr\Log\LoggerInterface; class Example extends Command { protected $signature = 'example'; public function handle(ExampleService $service, LoggerInterface $logger) { try { $service->example(); } catch (\Exception $exception) { $logger->critical('Example error', [ 'exception' => $exception, ]); } } } 

أين تكتب


النظر في الخيارات التالية.


  1. وفقا لتطبيق عامل 12 وبعض التوصيات الأخرى ، تحتاج إلى الكتابة في stdout ، stderr من وقت تشغيل التطبيق. للقيام بذلك ، يمكنك تحديد php://stdout * في config logger.
  2. تجاهل 12 عامل ، عامل ميناء والكتابة إلى الملفات. يتيح لك Laravel (Monolog) إمكانية تكوين تدوير السجل. يمكن جمع المزيد من الرسائل من الملفات باستخدام Filebeat وإرسالها إلى Logstash للتحليل.
  3. إرسال سجلات من التطبيق مباشرة أخرى ، على سبيل المثال ، عبر UDP لزيادة الأداء.
  4. الجمع بين الحلول. الكتابة إلى الملفات التي تستخدم Filebeat سيتم جمعها وإرسالها إلى Logstash. اكتب stderr في الحاوية حتى تتمكن من استخدام أوامر docker logs جاهزًا لجمع السجلات بسهولة من بيئة تزامن الحاوية. في هذه الحالة ، يمكنك كتابة بعض القنوات محليًا فقط ، والبعض الآخر يرسل عبر الشبكة.

* في php-fpm 7.2 ، عند كتابة سجلات إلى stdout ، نحصل على "تحذير: تم إخبار الطفل X [pool www] بـ stdout ..." ، ويتم اقتطاع الرسائل الطويلة. حل واحد لهذه المشكلة هو هنا . لا توجد مشكلة من هذا القبيل في php-fpm 7.3.


خيارات تنسيق التسجيل:


  • قابل للقراءة من قبل الإنسان (فواصل الأسطر ، المسافات البادئة ، إلخ.)
  • قراءة الجهاز (عادة json)
  • كلا التنسيقين في آن واحد: يمكن قراءته آلياً في stdout لمزيد من التوجيه ، ويمكن قراءته من قبل الإنسان في حالة حدوث مشكلات توجيه مفاجئة وتصحيح سريع

يفترض أي من الخيارات أن السجلات يتم توجيهها - على الأقل ، يتم إرسالها إلى نظام معالجة واحد (تخزين) من السجلات للأسباب التالية:


  1. التخزين طويل الأجل والأرشفة
  2. تتجه على نطاق واسع
  3. نظام إخطار مرن للحدث

عامل الميناء لديه القدرة على تحديد مدير السجل. json-file الافتراضي هو json-file ، أي يضيف عامل النقل الإخراج من الحاوية إلى ملف json على المضيف. إذا اخترنا مدير سجل يرسل السجلات في مكان ما عبر الشبكة ، فلن نتمكن بعد ذلك من استخدام docker logs . إذا تم اختيار stdout / stderr من الحاوية كمكان وحيد لتسجيل سجلات التطبيق ، ثم في حالة وجود مشاكل في الشبكة أو مشاكل في مستودع واحد ، فقد لا يكون من الممكن استخراج السجلات بسرعة لتصحيح الأخطاء.


يمكننا استخدام عامل إرساء ملف json و Filebeat. سوف نتلقى كل من السجلات المحلية ومزيد من التوجيه. تجدر الإشارة هنا هو سمة أخرى من سمات عامل ميناء. عند تسجيل حدث أطول من 16 كيلو بايت ، يكسر عامل النقل السجل بالرمز \n ، والذي يخلط بين العديد من جامعي السجل. هناك مشكلة حول هذا الموضوع. لا يمكن حل المشكلة من جانب عامل ميناء ، لذلك تم حلها من قبل جامعي. مع بعض الإصدار ، يدعم Filebeat سلوك عامل الالتحام هذا ويجمع الأحداث بشكل صحيح.


ما مزيج من جميع إمكانيات الوجهات وتنسيقات التسجيل التي يمكنك اختيارها لمشروعك بنفسك.


باستخدام Filebeat + ELK + Elastalert


باختصار ، يمكن وصف دور كل خدمة على النحو التالي:


  • Filebeat - يجمع الأحداث من الملفات ويرسل
  • Logstash - يوزع الأحداث ويرسل
  • Elasticsearch - مخازن الأحداث المنظمة
  • Kibana - يعرض الأحداث (الرسوم البيانية والتجمعات وما إلى ذلك)
  • Elastalert - يرسل تنبيهات بناء على الطلبات

بالإضافة إلى ذلك ، يمكنك: zabbix ، metricbeat ، grafana والمزيد.


الآن المزيد عن كل.


Filebeat


يمكنك تشغيل كخدمة منفصلة على المضيف ، يمكنك استخدام حاوية قفص الاتهام منفصلة. للعمل مع دفق الأحداث من عامل الميناء ، فإنه يستخدم مسار المضيف /var/lib/docker/containers/*/*.log . يحتوي Filebeat على مجموعة واسعة من الخيارات التي يمكنك من خلالها ضبط السلوك في المواقف المختلفة (تتم إعادة تسمية الملف وحذف الملف وما شابه). يمكن لـ Filebeat نفسها تحليل json داخل الحدث ، لكن لا يمكن لـ json أيضًا الدخول في الأحداث ، مما يؤدي إلى حدوث خطأ. تتم معالجة الأحداث بشكل أفضل في مكان واحد.


تكوين جزء ل Filebeat 6
 filebeat.inputs: - type: docker containers: ids: - "*" processors: - add_docker_metadata: ~ 

Logstash


قادر على قبول الأحداث من العديد من المصادر ، لكن هنا نفكر في Filebeat.
في كل حدث ، إلى جانب الحدث نفسه من stdout / stderr ، هناك بيانات وصفية (مضيف ، حاوية ، إلخ). هناك العديد من عوامل تصفية المعالجة المضمّنة: تحليل بفواصل زمنية منتظمة ، تحليل json ، تعديل ، إضافة ، حذف الحقول ، إلخ. مناسب لتحليل كل من سجلات التطبيق و nginx access.log بأي تنسيق. قادر على نقل البيانات إلى مستودعات مختلفة ، ولكن هنا نعتبر Elasticsearch.


جزء التكوين تصفية تصفية Logstash
 if [status] { date { match => ["timestamp_nginx_access", "dd/MMM/yyyy:HH:mm:ss Z"] target => "timestamp_nginx" remove_field => ["timestamp_nginx_access"] } mutate { convert => { "bytes_sent" => "integer" "body_bytes_sent" => "integer" "request_length" => "integer" "request_time" => "float" "upstream_response_time" => "float" "upstream_connect_time" => "float" "upstream_header_time" => "float" "status" => "integer" "upstream_status" => "integer" } remove_field => [ "message" ] rename => { "@timestamp" => "event_timestamp" "timestamp_nginx" => "@timestamp" } } } 

Elasticsearch


يعد Elasticsearch أداة قوية للغاية لمجموعة واسعة من المهام ، ولكن لغرض مراقبة السجلات يمكن استخدامه مع العلم بحد أدنى معين.
الأحداث المحفوظة هي وثيقة ، ويتم تخزين الوثائق في الفهارس.
كل فهرس هو مخطط يتم فيه تحديد نوع لكل حقل مستند. لا يمكنك حفظ حدث في الفهرس إذا كان هناك حقل واحد على الأقل به نوع خاطئ.
تتيح لك الأنواع المختلفة القيام بعمليات مختلفة على مجموعة من المستندات (للأرقام - المجموع ، الحد الأدنى ، الحد الأقصى ، المتوسط ​​، إلخ ، للسلاسل - البحث الغامض ، وما إلى ذلك).
بالنسبة للسجلات ، توصي الإدارة عادة باستخدام الفهارس اليومية - وهو فهرس جديد كل يوم.


يعد ضمان التشغيل المستقر لـ Elasticsearch مع نمو حجم البيانات مهمة تتطلب معرفة أعمق حول هذه الأداة. ولكن حلاً سريعًا لمشكلة الاستقرار ، يمكنك اختيار حذف البيانات القديمة تلقائيًا. للقيام بذلك ، أقترح تقسيم مستويات الأحداث في logstash في مؤشرات مختلفة. سيسمح ذلك لفترة أطول بتخزين الأحداث النادرة ولكن الأكثر أهمية.


لوغستاش تكوين مقتطف الإخراج
 output { if [fields][log_type] == "app_log" { if [level] in ["DEBUG", "INFO", "NOTICE"] { elasticsearch { hosts => "${ES_HOST}" index => "logstash-app-log-debug-%{+YYYY.MM.dd}" } } else { elasticsearch { hosts => "${ES_HOST}" index => "logstash-app-log-error-%{+YYYY.MM.dd}" } } } } 

لإزالة الفهارس القديمة تلقائيًا ، أقترح استخدام برنامج من Elastic Curator . يتم إضافة إطلاق البرنامج إلى جدول Cron ، يمكن تخزين التكوين نفسه في ملف منفصل.


جزء من التكوين لإزالة الفهارس القديمة
 action: delete_indices description: logstash-app-log-error options: ignore_empty_list: True filters: - filtertype: pattern kind: prefix value: logstash-app-log-error- - filtertype: age source: name direction: older timestring: '%Y.%m.%d' unit: months unit_count: 6 

, Filebeat Logstash, . Elasticsearch -- , , .


Kibana


Kibana . -, Elasticsearch. .


Kibana — Discovery . , Discovery app warning , time, message, exception class, host, client_id.


, Discovery nginx, 404 time, message, request, status.
Kibana , : , , . , ( ).


صورة


Elastalert


Elastalert Elasticsearch . , . , .
, (), .


:


  • ALERT, EMERGENCY. — 10
  • CRITICAL. — 30
  • , N X M
  • 10 INFO 3
  • nginx 200, 201, 304 75% , 50

 name: Blacklist ALERT, EMERGENCY type: blacklist index: logstash-app-* compare_key: "level" blacklist: - "ALERT" - "EMERGENCY" realert: minutes: 5 alert: - "slack" 

. , , . Kibana.


, , http- 75% , , , , . - , , , .


, , , , Kibana, .


5 . , , , , , .


, . .


Kibana . .



docker-. , , staging- production-, .


, Elastalert, . Elastalert ,
envsubst < /opt/elastalert/config.dist.yaml > /opt/elastalert/config.yaml entrypoint- , .


, , , .


Makefile
 build: docker build -t some-registry/elasticsearch elasticsearch docker build -t some-registry/logstash logstash docker build -t some-registry/kibana kibana docker build -t some-registry/nginx nginx docker build -t some-registry/curator curator docker build -t some-registry/elastalert elastalert push: docker push some-registry/elasticsearch docker push some-registry/logstash docker push some-registry/kibana docker push some-registry/nginx docker push some-registry/curator docker push some-registry/elastalert pull: docker pull some-registry/elasticsearch docker pull some-registry/logstash docker pull some-registry/kibana docker pull some-registry/nginx docker pull some-registry/curator docker pull some-registry/elastalert prepare: docker network create -d bridge elk-network || echo "ok" stop: docker rm -f kibana || true docker rm -f logstash || true docker rm -f elasticsearch || true docker rm -f nginx || true docker rm -f elastalert || true run-logstash: docker rm -f logstash || echo "ok" docker run -d --restart=always --network=elk-network --name=logstash -p 127.0.0.1:5001:5001 -e "LS_JAVA_OPTS=-Xms256m -Xmx256m" -e "ES_HOST=elasticsearch:9200" some-registry/logstash run-kibana: docker rm -f kibana || echo "ok" docker run -d --restart=always --network=elk-network --name=kibana -p 127.0.0.1:5601:5601 --mount source=elk-kibana,target=/usr/share/kibana/optimize some-registry/kibana run-elasticsearch: docker rm -f elasticsearch || echo "ok" docker run -d --restart=always --network=elk-network --name=elasticsearch -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" --mount source=elk-esdata,target=/usr/share/elasticsearch/data some-registry/elasticsearch run-nginx: docker rm -f nginx || echo "ok" docker run -d --restart=always --network=elk-network --name=nginx -p 80:80 -v /root/elk/.htpasswd:/etc/nginx/.htpasswd some-registry/nginx run-elastalert: docker rm -f elastalert || echo "ok" docker run -d --restart=always --network=elk-network --name=elastalert --env-file=./elastalert/.env some-registry/elastalert run: prepare run-elasticsearch run-kibana run-logstash run-elastalert delete-old-indices: docker run --rm --network=elk-network -e "ES_HOST=elasticsearch:9200" some-registry/curator curator --config /curator/curator.yml /curator/actions.yml 

:


  • 80 nginx, basic auth Kibana
  • Logstash . ssh-
  • nginx
  • , docker-
  • , .env- nginx-
  • *_JAVA_OPTS , 4GB RAM ( ES).

, xpack-.


docker-compose. , , Dockerfile-, Filebeat, Logstash, , , , , VCS.


. . , ( Laravel scheduler), , 5 . ALERT. , . , , .


استنتاج


, , , . . , - . . , , .

Source: https://habr.com/ru/post/ar456676/


All Articles