تتمثل المهمة الأولى التي يواجهها المطورين الذين يبدأون البرنامج في JavaScript في معظم الأحيان في كيفية تسجيل الأحداث في سجل وحدة التحكم باستخدام طريقة
console.log
. للبحث عن معلومات حول تصحيح شفرة JavaScript ، ستجد المئات من مقالات المدونة ، بالإضافة إلى إرشادات حول StackOverflow ، تنصحك بـ "ببساطة" إخراج البيانات إلى وحدة التحكم من خلال طريقة
console.log
. هذه ممارسة شائعة لدرجة أنني اضطررت إلى تقديم قواعد لمراقبة جودة الكود ، مثل
no-console
، حتى لا أترك إدخالات السجل العشوائي في رمز الإنتاج. ولكن ماذا لو كنت بحاجة إلى تسجيل حدث على وجه التحديد لتقديم معلومات إضافية؟
تتناول هذه المقالة المواقف المختلفة التي تحتاج فيها إلى الاحتفاظ بسجلات ؛ يُظهر الفرق بين أساليب console.log و console.error في Node.js ويوضح كيفية تمرير وظيفة التسجيل إلى المكتبات دون زيادة تحميل وحدة تحكم المستخدم.

الأسس النظرية للعمل مع Node.js
يمكن استخدام طريقتي console.log و console.error في المستعرض وفي Node.js. ومع ذلك ، عند استخدام Node.js ، هناك شيء واحد مهم يجب تذكره. إذا قمت بإنشاء التعليمة البرمجية التالية في Node.js باستخدام ملف يسمى
index.js
،

ثم قم بتنفيذه في الجهاز الطرفي باستخدام
node index.js
، وستكون نتائج تنفيذ الأمر واحدة فوق الأخرى:

على الرغم من أنها تبدو متشابهة ، فإن النظام يعالجها بشكل مختلف. إذا نظرت إلى القسم الخاص بتشغيل
console
في
وثائق Node.js ، اتضح أن
console.log
يطبع النتيجة عبر
stdout
، و
console.error
يطبع من خلال
stderr
.
يمكن أن تعمل كل عملية مع ثلاثة تدفقات (
stream
) افتراضيًا:
stdin
و
stdout
و
stderr
. يعالج تيار
stdin
المدخلات لعملية ما ، على سبيل المثال ، نقرات الأزرار أو الإخراج المعاد توجيهه (المزيد في هذا أدناه). دفق الإخراج القياسي
stdout
هو لإخراج بيانات التطبيق. أخيرًا ، تم تصميم دفق أخطاء
stderr
القياسي لعرض رسائل الخطأ. إذا كنت بحاجة إلى معرفة ما
stderr
ومتى يجب استخدامه ، اقرأ
هذه المقالة .
باختصار ، يمكن استخدامه لاستخدام معيدي التوجيه (
>
) ومشغلي خطوط الأنابيب (
|
) للتعامل مع الأخطاء والمعلومات التشخيصية بشكل منفصل عن النتائج الفعلية للتطبيق. إذا كان المشغل
>
يسمح لك بإعادة توجيه إخراج نتيجة الأمر إلى ملف ، ثم باستخدام المشغل
2>
يمكنك إعادة توجيه إخراج قطار خطأ
stderr
إلى ملف. على سبيل المثال ، يرسل هذا الأمر
مرحبًا بك إلى ملف
hello.log
،
وداعًا إلى ملف
error.log
.


متى أحتاج إلى كتابة الأحداث إلى السجل؟
الآن وبعد أن استعرضنا الجوانب الفنية التي تقوم عليها عملية التسجيل ، دعنا ننتقل إلى سيناريوهات مختلفة تحتاج فيها إلى تسجيل الأحداث. عادة ، تندرج هذه السيناريوهات في واحدة من عدة فئات:
تتناول هذه المقالة فقط السيناريوهات الثلاثة الأخيرة المستندة إلى Node.js.
تسجيل لتطبيقات الخادم
هناك عدة أسباب لتسجيل الأحداث التي تحدث على الخادم. على سبيل المثال ، يسمح لك تسجيل الطلبات الواردة بالحصول على إحصائيات حول عدد المرات التي يواجه فيها المستخدمون أخطاء 404 ، وما السبب في ذلك ، أو تطبيق عميل
User-Agent
المستخدم قيد الاستخدام. يمكنك أيضًا معرفة الوقت الذي حدث فيه الخطأ وسببه.
لتجربة المواد الواردة في هذا الجزء من المقالة ، تحتاج إلى إنشاء كتالوج جديد للمشروع. في دليل المشروع ، قم بإنشاء
index.js
للرمز الذي سيتم استخدامه ، وقم بتنفيذ الأوامر التالية لبدء المشروع والتثبيت
express
:

لقد قمنا بإعداد خادم مع برنامج وسيط ، والذي سوف يسجل كل طلب في وحدة التحكم باستخدام طريقة
console.log
. نضع الأسطر التالية في ملف
index.js
:

يستخدم هذا
console.log('%O', req)
لتسجيل الكائن بأكمله في السجل. من وجهة نظر البنية الداخلية ، تستخدم طريقة
util.forma
t ، والتي ، بالإضافة إلى
%O
تدعم العناصر النائبة الأخرى. يمكن العثور على معلومات عنها في
وثائق Node.js.عند تنفيذ
node index.js
لبدء تشغيل الخادم والتبديل إلى
المضيف المحلي : 3000 ، تعرض وحدة التحكم الكثير من المعلومات غير الضرورية:

إذا كنت تستخدم بدلاً من ذلك
console.log('%s', req)
حتى لا تعرض الكائن بالكامل ، فلن تحصل على الكثير من المعلومات:

يمكنك كتابة وظيفة التسجيل الخاصة بك ، والتي ستقوم بإخراج البيانات الضرورية فقط ، ولكن عليك أولاً تحديد المعلومات المطلوبة. على الرغم من أن التركيز عادةً ما يكون على محتوى الرسالة ، إلا أنه في الواقع من الضروري في كثير من الأحيان الحصول على معلومات إضافية ، والتي تشمل:
- الطابع الزمني - لمعرفة متى وقعت الأحداث ؛
- اسم الكمبيوتر / الخادم - إذا كان النظام الموزع قيد التشغيل ؛
- معرف العملية - إذا كان يتم تشغيل العديد من عمليات العقدة باستخدام ، على سبيل المثال ،
pm2
؛ - رسالة - رسالة فعلية مع بعض المحتوى ؛
- تتبع المكدس - إذا تم تسجيل خطأ ؛
- المتغيرات / المعلومات الإضافية.
بالإضافة إلى ذلك ، نظرًا لأنه في أي حال ، يتم إخراج كل شيء إلى تدفقات
stdout
و
stderr
، هناك حاجة إلى الاحتفاظ بمجلة في مستويات مختلفة ، وكذلك تكوين إدخالات دفتر اليومية وتصفيتها وفقًا للمستوى.
يمكن تحقيق ذلك من خلال الوصول إلى أجزاء مختلفة من
process
وكتابة عدة أسطر من التعليمات البرمجية في JavaScript. ومع ذلك ، Node.js لافت للنظر لأنه يحتوي بالفعل على نظام بيئي
npm
والعديد من المكتبات التي يمكن استخدامها لهذه الأغراض. وتشمل هذه:
pino
winston
- هدير
- بنيان (لم يتم تحديث هذه المكتبة منذ عامين).
غالبًا ما يفضل Pino لأنه سريع وله نظام بيئي خاص به. دعونا نرى كيف يمكن أن تساعد
pino
تسجيل. ميزة أخرى لهذه المكتبة هي حزمة
express-pino-logger
، التي تسمح لك بتسجيل الطلبات.
تثبيت
pino
و
express-pino-logger
:

بعد ذلك ، نقوم بتحديث ملف
index.js
لاستخدام مسجل الأحداث والبرامج الوسيطة:

في هذه
app.use
،
app.use
الأحداث لـ
pino
app.use
إلى
express-pino-logger
لإنشاء برنامج جديد لتسجيل الأحداث عبر الأنظمة الأساسية والذي يمكنك من خلاله الاتصال بـ
app.use
. بالإضافة إلى ذلك ،
console.log
استبدال
logger.info
في
logger.info
بواسطة
logger.info
logger.debug
إضافة
logger.debug
إلى المسار لعرض مستويات مختلفة من السجل.
إذا قمت بإعادة تشغيل الخادم عن طريق تنفيذ
node index.js
مرارًا وتكرارًا ، فستحصل على نتيجة مختلفة في الإخراج ، حيث سيتم إخراج كل سطر / سطر بتنسيق JSON. مرة أخرى ، انتقل إلى
المضيف المحلي : 3000 لرؤية سطر جديد آخر بتنسيق JSON.

من بين البيانات بتنسيق JSON ، يمكنك العثور على المعلومات المذكورة سابقًا ، مثل الطابع الزمني. لاحظ أيضًا أنه
logger.debug
يتم عرض رسالة
logger.debug
. لجعلها مرئية ، تحتاج إلى تغيير مستوى السجل الافتراضي. بعد إنشاء مثيل لتسجيل حدث المسجل ، تم تعيين قيمة
process.env.LOG_LEVEL
. هذا يعني أنه يمكنك تغيير القيمة أو قبول قيمة
info
الافتراضية.
LOG_LEVEL=debug node index.js
تشغيل
LOG_LEVEL=debug node index.js
، نقوم بتغيير مستوى السجل.
قبل القيام بذلك ، من الضروري حل مشكلة تنسيق الإخراج ، والتي ليست مريحة للغاية للإدراك في الوقت الحالي. هذه الخطوة متعمدة. وفقًا لفلسفة
pino
، لأسباب تتعلق بالأداء ، من الضروري نقل معالجة إدخالات دفتر اليومية إلى عملية منفصلة ، وتمرير الإخراج (باستخدام
|
مشغل). تتضمن العملية ترجمة الإخراج إلى تنسيق أكثر ملاءمة للإدراك البشري ، أو تحميله على السحابة. يتم تنفيذ هذه المهمة عن طريق أدوات
transports
تسمى
transports
. تحقق من
وثائق مجموعة أدوات transports
pino
لماذا لا يتم إخراج أخطاء
pino
من خلال
stderr
.
لعرض نسخة أكثر قابلية للقراءة من المجلة ، استخدم أداة
pino-pretty
. تشغيل في المحطة:

يتم نقل جميع إدخالات السجل باستخدام
|
تحت تصرف
pino-pretty
، والذي بسببه يتم "إخراج" الإخراج ، والذي سيحتوي فقط على معلومات مهمة معروضة بألوان مختلفة. إذا قمت باستعلام
المضيف المحلي : 3000 مرة أخرى ، يجب أن تظهر رسالة تصحيح الأخطاء.

لجعل إدخالات دفتر اليومية أكثر قابلية للقراءة أو تحويلها ، هناك العديد من أدوات الإرسال. حتى يمكن عرضها باستخدام الرموز التعبيرية باستخدام
pino-colada
. هذه الأدوات ستكون مفيدة للتنمية المحلية. عندما يكون الخادم قيد الإنتاج ، قد يكون من الضروري نقل بيانات السجل باستخدام
أداة أخرى ، أو كتابتها على القرص باستخدام
>
لمزيد من المعالجة ، أو القيام بعمليتين في نفس الوقت باستخدام أمر محدد ، على سبيل المثال
tee
.
تتحدث
الوثيقة أيضًا عن تدوير ملفات السجل وتصفية وكتابة بيانات السجل إلى ملفات أخرى.
يوميات المكتبة
من خلال استكشاف طرق لتنظيم التسجيل الفعال لتطبيقات الخادم ، يمكنك استخدام نفس التقنية لمكتباتك الخاصة.
المشكلة هي أنه في حالة المكتبة ، قد تحتاج إلى الاحتفاظ بسجل لأغراض تصحيح الأخطاء دون تحميل تطبيق العميل. على العكس من ذلك ، يجب أن يكون العميل قادرًا على تنشيط السجل إذا كان التصحيح ضروريًا. بشكل افتراضي ، لا ينبغي أن تسجل المكتبة الإخراج ، مع إعطاء المستخدم هذا الحق.
وخير مثال على ذلك هو الإطار
express
. تحدث العديد من العمليات في البنية الداخلية لإطار العمل
express
، مما قد يتسبب في الاهتمام بدراسته بشكل أعمق أثناء تصحيح أخطاء التطبيقات. تنص
وثائق إطار العمل express
أنه يمكنك إضافة
DEBUG=express:*
إلى بداية الأمر كما يلي:

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

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

قم بإنشاء ملف جديد يسمى
random-id.j
s يحاكي المكتبة ويضع الكود التالي فيه:

نتيجة لذلك ، سيتم إنشاء مسجّل حدث
debug
جديد باستخدام
mylib:randomid
، حيث سيتم بعد ذلك تسجيل رسالتين. نستخدمها في
index.js
من القسم السابق:

إذا قمت ببدء تشغيل الخادم مرة أخرى ، بإضافة
DEBUG=mylib:randomid node index.js
هذه المرة ، فسيتم عرض إدخالات سجل التصحيح لـ "المكتبة" الخاصة بنا:

إذا أراد مستخدمو المكتبة وضع معلومات تصحيح الأخطاء في إدخالات سجل
pino
، فيمكنهم استخدام مكتبة تسمى
pino-debug
تم إنشاؤها بواسطة أمر
pino
لتنسيق هذه الإدخالات بشكل صحيح.
تثبيت المكتبة:

قبل استخدام
debug
لأول مرة ، يجب تهيئة
pino-debug
. أسهل طريقة للقيام بذلك هي استخدام
إشارات -r
أو - طلب طلب وحدة نمطية قبل تشغيل البرنامج النصي. نقوم بإعادة تشغيل الخادم باستخدام الأمر (شريطة أن
pino-colada
تثبيت
pino-colada
):

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

واجهة سطر الأوامر (CLI) الإخراج
الحالة الأخيرة التي تناقشها هذه المقالة هي تسجيل واجهة سطر الأوامر. على نحو مفضل ، يتم الاحتفاظ بالسجل الذي يسجل الأحداث المتعلقة بمنطق البرنامج بشكل منفصل عن السجل لتسجيل بيانات واجهة سطر الأوامر. لتسجيل أي أحداث متعلقة بمنطق البرنامج ، تحتاج إلى استخدام مكتبة معينة ، على سبيل المثال
debug
. في هذه الحالة ، يمكنك إعادة استخدام منطق البرنامج دون أن يقتصر على سيناريو واحد باستخدام واجهة سطر الأوامر.
من خلال إنشاء واجهة سطر أوامر باستخدام Node.js ، يمكنك إضافة ألوان متنوعة أو كتل قيمة متغيرة أو أدوات تنسيق لإعطاء الواجهة مظهرًا جذابًا للعيان. ومع ذلك ، تحتاج إلى أن تضع في الاعتبار العديد من السيناريوهات.
وفقًا لأحدها ، يمكن استخدام الواجهة في سياق نظام تكامل مستمر (CI) ، وفي هذه الحالة من الأفضل التخلي عن تنسيق الألوان وعرض النتائج الزائد بصريًا. تحتوي بعض أنظمة التكامل المستمر على مجموعة
CI
. يمكنك التحقق من أنك في نظام تكامل مستمر باستخدام حزمة
is-ci
، التي تدعم العديد من هذه الأنظمة.
تقوم بعض المكتبات ، مثل
chalk
، بتعريف أنظمة التكامل المستمر وتجاوز إخراج النص الملون إلى وحدة التحكم. دعونا نرى كيف يعمل.
قم بتثبيت
chalk
باستخدام الأمر npm
install chalk
chalk وقم بإنشاء ملف يسمى
cli.js
ضع الأسطر التالية في الملف:

الآن ، إذا قمت بتنفيذ هذا البرنامج النصي باستخدام
node cli.js
، فسيتم تقديم النتائج باستخدام ألوان مختلفة:

ولكن إذا قمت بتنفيذ البرنامج النصي باستخدام
CI=true node cli.js
، فسيتم إلغاء تنسيق الألوان للنصوص:

في سيناريو آخر يستحق التذكر ،
stdout
تشغيل
stdout
في الوضع الطرفي ، أي البيانات هي الإخراج إلى المحطة. في هذه الحالة ، يمكن عرض النتائج بشكل جيد باستخدام
boxen
. وإلا ، سيتم إعادة توجيه الإخراج على الأرجح إلى ملف أو إلى مكان آخر.
يمكنك التحقق من تشغيل تدفقات
stdin
أو
stdout
أو
stderr
في الوضع الطرفي من خلال النظر إلى سمة
isTTY
للتيار المقابل. على سبيل المثال ،
process.stdout.isTTY
.
TTY
يعني "teletypewriter" وفي هذه الحالة تم تصميمه خصيصًا للمحطة.
قد تختلف القيم لكل من مؤشرات الترابط الثلاثة ، اعتمادًا على كيفية بدء عمليات Node.js. يمكن العثور على معلومات مفصلة عن ذلك في
وثائق Node.js ، في قسم "الإدخال / الإخراج من العمليات" .
دعونا نرى كيف تختلف قيمة
process.stdout.isTTY
في المواقف المختلفة.
cli.js
ملف
cli.js
للتحقق منه:

الآن قم بتشغيل
node cli.js
في المحطة الطرفية وانظر الكلمة
true
، وبعد ذلك يتم عرض الرسالة
node cli.js
الملون:

بعد ذلك ، نعيد تنفيذ الأمر ، لكننا نعيد توجيه الإخراج إلى ملف ، ثم نعرض المحتويات:

هذه المرة ، ظهرت الكلمة
undefined
في الجهاز ، متبوعة برسالة معروضة بخط عديم اللون ، لأن إعادة توجيه تيار
stdout
من وضع الجهاز. يستخدم
chalk
هنا أداة
supports-color
، والتي من وجهة نظر الهيكل الداخلي تتحقق من
isTTY
للتيار المقابل.

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