مسجل لكل شيء تقريبًا.
راجع دليل الترقية لمزيد من المعلومات. نرحب بتقارير الأخطاء والعلاقات العامة!
[email protected]
؟ يرجى ملاحظة أن الوثائق أدناه مخصصة لـ winston@3
. اقرأ وثائق [email protected]
.
تم تصميم winston
لتكون مكتبة تسجيل بسيطة وعالمية مع دعم لعمليات النقل المتعددة. يعد النقل في الأساس جهاز تخزين لسجلاتك. يمكن أن يحتوي كل مسجل winston
على وسائل نقل متعددة (انظر: وسائل النقل) تم تكوينها على مستويات مختلفة (انظر: مستويات التسجيل). على سبيل المثال، قد يرغب المرء في تخزين سجلات الأخطاء في موقع بعيد دائم (مثل قاعدة بيانات)، ولكن يتم إخراج جميع السجلات إلى وحدة التحكم أو ملف محلي.
يهدف winston
إلى فصل أجزاء من عملية التسجيل لجعلها أكثر مرونة وقابلة للتوسيع. يتم الاهتمام بدعم المرونة في تنسيق السجل (راجع: التنسيقات) والمستويات (راجع: استخدام مستويات التسجيل المخصصة)، والتأكد من فصل واجهات برمجة التطبيقات (APIs) عن تنفيذ تسجيل النقل (أي كيفية تخزين/فهرسة السجلات، راجع: إضافة مخصص النقل) إلى واجهة برمجة التطبيقات (API) التي عرضوها للمبرمج.
ليرة تركية؟ تحقق من مثال البدء السريع في ./examples/
. هناك عدد من الأمثلة الأخرى في ./examples/*.js
. ألا ترى مثالاً تعتقد أنه يجب أن يكون موجودًا؟ إرسال طلب سحب لإضافته!
الطريقة الموصى بها لاستخدام winston
هي إنشاء المسجل الخاص بك. إن أبسط طريقة للقيام بذلك هي استخدام winston.createLogger
:
const Winston = require('winston');const logger = Winston.createLogger({ المستوى: 'info'، التنسيق: Winston.format.json()، defaultMeta: {service: 'user-service' }، النقل: [ / // - اكتب جميع السجلات بمستوى أهمية `خطأ` أو أعلى إلى `خطأ.سجل` // (أي خطأ، فادح، ولكن ليس المستويات الأخرى) // new Winston.transports.File({ filename: 'error.log'، المستوى: 'error' })، // // - اكتب جميع السجلات بمستوى أهمية `info` أو أعلى إلى `combined.log` // (على سبيل المثال، فادح، وخطأ، وتحذير، ومعلومات ، ولكن ليس التتبع) // new Winston.transports.File({ filename: 'combined.log' }), ],});//// إذا لم نكن في مرحلة الإنتاج، فقم بتسجيل الدخول إلى "وحدة التحكم" باستخدام شكل:// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `//if (process.env.NODE_ENV !== 'production') { logger.add(new Winston. Transports.Console({ التنسيق: Winston.format.simple(), }));}
يمكنك أيضًا تسجيل الدخول مباشرة عبر المُسجل الافتراضي المكشوف بواسطة require('winston')
، ولكن المقصود من هذا فقط هو أن يكون مُسجلًا مشتركًا مناسبًا لاستخدامه في جميع أنحاء التطبيق الخاص بك إذا اخترت ذلك. لاحظ أن المسجل الافتراضي لا يحتوي على أي وسائل نقل بشكل افتراضي. تحتاج إلى إضافة وسائل النقل بنفسك، وقد يؤدي ترك المسجل الافتراضي بدون أي وسائل نقل إلى حدوث مشكلة في استخدام الذاكرة بشكل كبير.
تحفيز
بداية سريعة
الاستخدام
جدول المحتويات
التسجيل
إنشاء المسجل الخاص بك
التدفقات و objectMode
وكائنات info
التنسيقات
الجمع بين التنسيقات
استيفاء السلسلة
تصفية كائنات info
إنشاء صيغ مخصصة
مستويات التسجيل
استخدام مستويات التسجيل
استخدام مستويات التسجيل المخصصة
وسائل النقل
وسائل نقل متعددة من نفس النوع
إضافة وسائل النقل المخصصة
خيارات النقل المشتركة
الاستثناءات
التعامل مع الاستثناءات غير المكتشفة باستخدام Winston
للخروج أو عدم الخروج
الرفض
التعامل مع رفض الوعد غير المكتشف مع وينستون
التنميط
سجلات التدفق
سجلات الاستعلام
مزيد من القراءة
باستخدام المسجل الافتراضي
في انتظار كتابة السجلات في winston
العمل مع العديد من قطع الأشجار في winston
تنقل وحدة التحكم في التوجيه الرسائل إلى وحدة التحكم بدلاً من stdout وstderr
تثبيت
تشغيل الاختبارات
تتوافق مستويات التسجيل في winston
مع ترتيب الخطورة المحدد بواسطة RFC5424: يُفترض أن خطورة جميع المستويات تصاعدية رقميًا من الأكثر أهمية إلى الأقل أهمية.
مستويات const = { خطأ: 0، تحذير: 1، معلومات: 2، http: 3، مطول: 4، تصحيح: 5، سخيف: 6}؛
يمكنك البدء بإنشاء مُسجل باستخدام winston.createLogger
:
const logger = Winston.createLogger({ Transports: [ new Winston.transports.Console(), new Winston.transports.File({ filename: 'combined.log' }) ]});
يقبل المسجل المعلمات التالية:
اسم | تقصير | وصف |
---|---|---|
level | 'info' | قم بالتسجيل فقط إذا كان info.level أقل من هذا المستوى أو يساويه |
levels | winston.config.npm.levels | المستويات (والألوان) التي تمثل أولويات السجل |
format | winston.format.json | تنسيق رسائل info (راجع: التنسيقات) |
transports | [] (لا توجد وسائل نقل) | مجموعة من أهداف التسجيل لرسائل info |
exitOnError | true | إذا كانت خاطئة، فلن تتسبب الاستثناءات التي تمت معالجتها في process.exit |
silent | false | إذا كان هذا صحيحًا، فسيتم منع كافة السجلات |
سيتم تعريف المستويات المقدمة لـ createLogger
على أنها طرق ملائمة يتم إرجاعها على logger
.
//// Logging//logger.log({level: 'info', message: 'مرحبًا بملفات السجل الموزعة!'});logger.info('مرحبًا مرة أخرى بالسجلات الموزعة');
يمكنك إضافة وسائل النقل أو إزالتها من logger
بمجرد تقديمها لك من winston.createLogger
:
ملفات const = new Winston.transports.File({ filename: 'combined.log' });const console = new Winston.transports.Console();logger .clear() // إزالة كافة وسائل النقل .add(console) // إضافة نقل وحدة التحكم .add(files) // إضافة نقل الملف .remove(console); // إزالة نقل وحدة التحكم
يمكنك أيضًا إعادة تكوين مثيل winston.Logger
بالجملة باستخدام طريقة configure
:
const logger = Winston.createLogger({ Level: 'info', Transports: [ new Winston.transports.Console(), new Winston.transports.File({ filename: 'combined.log' }) ]});/// / يستبدل وسائل النقل السابقة بتلك الموجودة في التكوين الجديد بالجملة.//const DailyRotateFile = require('winston-daily-rotate-file');logger.configure({ المستوى: 'مطول', النقل: [ new DailyRotateFile(opts) ]});
يمكنك إنشاء أدوات تسجيل فرعية من أدوات التسجيل الموجودة لتمرير تجاوزات البيانات التعريفية:
const logger = Winston.createLogger({ Transports: [ new Winston.transports.Console(), ]});const ChildLogger = logger.child({ requestId: '451' });
من المحتمل أن يكون هناك خطأ في
.child
إذا كنت تقوم أيضًا بتوسيع فئةLogger
، وذلك بسبب بعض تفاصيل التنفيذ التي تجعلthis
الكلمة الأساسية تشير إلى أشياء غير متوقعة. استخدم بحذر.
objectMode
وكائنات info
في winston
، يتم التعامل مع مثيلات Logger
و Transport
على أنها تدفقات objectMode
تقبل كائن info
.
تمثل معلمة info
المتوفرة لتنسيق معين رسالة سجل واحدة. الكائن نفسه قابل للتغيير. يجب أن تحتوي كل info
على الأقل على خصائص level
message
:
const info = {level: 'info', // مستوى رسالة رسالة التسجيل: 'مرحبًا! تسجيل شيء ما؟ // يتم تسجيل الرسالة الوصفية.};
تعتبر الخصائص إلى جانب المستوى والرسالة بمثابة " meta
". أي:
const {level, message, ...meta } = info;
تضيف العديد من التنسيقات الموجودة في logform
نفسه خصائص إضافية:
ملكية | تمت إضافة التنسيق بواسطة | وصف |
---|---|---|
splat | splat() | موجة استيفاء سلسلة لرسائل نمط %d %s . |
timestamp | timestamp() | الطابع الزمني لاستلام الرسالة. |
label | label() | تسمية مخصصة مرتبطة بكل رسالة. |
ms | ms() | عدد المللي ثانية منذ رسالة السجل السابقة. |
كمستهلك، يمكنك إضافة أي خصائص ترغب فيها - يتم الحفاظ على الحالة الداخلية من خلال خصائص Symbol
:
Symbol.for('level')
(للقراءة فقط) : يساوي خاصية level
. يتم التعامل معه على أنه غير قابل للتغيير بكل التعليمات البرمجية.
Symbol.for('message'):
رسالة سلسلة كاملة تم تعيينها عن طريق "إنهاء التنسيقات":
json
logstash
printf
prettyPrint
simple
Symbol.for('splat')
: وسيطات استيفاء سلسلة إضافية. يُستخدم حصريًا بواسطة تنسيق splat()
.
يتم تخزين هذه الرموز في حزمة أخرى: triple-beam
بحيث يمكن لجميع مستهلكي logform
الحصول على نفس مرجع الرمز. أي:
const { LEVEL, MESSAGE, SPLAT } = require('triple-beam');console.log(LEVEL === الرمز.for('level'));// trueconsole.log(MESSAGE === الرمز.for( 'message'));// trueconsole.log(SPLAT === الرمز.for('splat'));// صحيح
ملاحظة: أي خاصية
{ message }
في كائنmeta
المقدم سيتم ربطها تلقائيًا بأيmsg
مقدمة بالفعل: على سبيل المثال، سيتم ربط ما يلي "world" بـ "hello":logger.log('error', 'hello', { message: 'world' });logger.info('hello', { message: 'world' });
يمكن الوصول إلى التنسيقات الموجودة في winston
من winston.format
. يتم تنفيذها في logform
، وهي وحدة منفصلة عن winston
. يتيح ذلك المرونة عند كتابة وسائل النقل الخاصة بك في حالة رغبتك في تضمين تنسيق افتراضي مع وسيلة النقل الخاصة بك.
في الإصدارات الحديثة من سلاسل قالب node
تكون ذات أداء عالٍ وهي الطريقة الموصى بها للقيام بمعظم تنسيقات المستخدم النهائي. إذا كنت تريد تنسيق سجلاتك حسب الطلب، winston.format.printf
هو الخيار المناسب لك:
const { createLogger, format, Transports } = require('winston');const { Combine, timestamp, label, printf } = format;const myFormat = printf(({ المستوى, الرسالة, التسمية, الطابع الزمني }) => { return ` ${timestamp} [${label}] ${level}: ${message}`;});const logger = createLogger({ format: Combine( label({ label: "مواء صحيح!" })، الطابع الزمني ()، myFormat)، وسائل النقل: [new Transports.Console()]});
لمعرفة التنسيقات المضمنة المتوفرة ومعرفة المزيد حول إنشاء تنسيقات التسجيل المخصصة الخاصة بك، راجع logform
.
يمكن دمج أي عدد من التنسيقات في تنسيق واحد باستخدام format.combine
. نظرًا لأن format.combine
لا يأخذ أي opts
، فإنه يقوم بإرجاع مثيل تم إنشاؤه مسبقًا للتنسيق المدمج كوسيلة راحة.
const { createLogger, format, Transports } = require('winston');const { Combine, timestamp, label, PrettyPrint } = format;const logger = createLogger({ format: Combine( label({ label: 'right meow!' } )، timestamp(), PrettyPrint() ), النقل: [new Transports.Console()]})logger.log({level: 'info', message: 'ما هو الوقت؟ الاختبار في؟'});// Outputs:// {level: 'info',// message: 'ما هو وقت الاختبار؟',// label: 'right meow!',// timestamp: ' 2017-09-30T03:57:26.875Z' }
يوفر أسلوب log
استيفاء السلسلة باستخدام util.format. يجب تمكينه باستخدام format.splat()
.
يوجد أدناه مثال يحدد تنسيقًا مع استيفاء سلسلة للرسائل باستخدام format.splat
ثم إجراء تسلسل لرسالة info
بأكملها باستخدام format.simple
.
const { createLogger, format, Transports } = require('winston');const logger = createLogger({ format: format.combine( format.splat(), format.simple() ))، وسائل النقل: [وسائل النقل الجديدة.Console() ]});// معلومات: رسالة اختبارية لسلسلتي {}logger.log('info', 'رسالة اختبار %s', 'سلسلتي');// معلومات: رسالة اختبارية 123 {}logger.log('info', 'test message %d', 123);// معلومات: رسالة اختبارية في الثانية الأولى {number: 123}logger.log('info', 'رسالة اختبارية %s, %s' , 'الأول', 'الثاني', { العدد: 123 });
info
إذا كنت ترغب في تصفية كائن info
معين بالكامل عند التسجيل، فما عليك سوى إرجاع قيمة خاطئة.
const { createLogger, format, Transports } = require('winston');// تجاهل رسائل السجل إذا كانت تحتوي على { خاص: صحيح }constignorPrivate = format((info, opts) => { if (info.private) { return false; } return info;});const logger = createLogger({ format: format.combine(ignorePrivate(), format.json() )، النقل: [new Transports.Console()]});// المخرجات: {"level": "خطأ"، "message": "خطأ عام للمشاركة"}logger.log({ المستوى: 'خطأ'، الرسالة: 'خطأ عام في share'});// لن تتم كتابة الرسائل التي تحتوي على { خاص: صحيح } عند تسجيل الدخول.logger.log({ خاص: صحيح، المستوى: 'خطأ'، الرسالة: 'هذا سري للغاية - قم بإخفائه.'}) ;
سيؤدي استخدام format.combine
إلى احترام أي قيم خاطئة يتم إرجاعها وإيقاف تقييم التنسيقات اللاحقة في السلسلة. على سبيل المثال:
const { format } = require('winston');const { Combine, timestamp, label } = format;const willNeverThrow = format.combine( format(info => { return false })(), // يتجاهل كل شيء format(info) => {رمي خطأ جديد("لم يتم الوصول إليه مطلقًا") })());
التنسيقات هي كائنات نموذجية (أي مثيلات الفئة) تحدد طريقة واحدة: transform(info, opts)
وإرجاع info
المتحولة:
info
: كائن يمثل رسالة السجل.
opts
: إعداد خاص بالمثيل الحالي للتنسيق.
ومن المتوقع أن يعودوا بأحد أمرين:
كائن info
يمثل وسيطة info
المعدلة. لا يلزم الحفاظ على مراجع الكائنات إذا كان الثبات مفضلاً. جميع التنسيقات المضمنة الحالية تعتبر info
قابلة للتغيير، ولكن يتم أخذ [immutablejs] في الاعتبار للإصدارات المستقبلية.
قيمة خاطئة تشير إلى أنه يجب على المتصل تجاهل وسيطة info
. (راجع: تصفية كائنات info
) أدناه.
تم تصميم winston.format
ليكون بسيطًا قدر الإمكان. لتحديد تنسيق جديد، ما عليك سوى تمرير دالة transform(info, opts)
للحصول على Format
جديد.
يمكن استخدام Format
المسمى الذي تم إرجاعه لإنشاء أكبر عدد ممكن من نسخ Format
المحدد حسب الرغبة:
const { format } = require('winston');const Volume = format((info, opts) => { if (opts.yell) { info.message = info.message.toUpperCase(); } else if (opts. Whisper) { info.message = info.message.toLowerCase(); } return info;});// `volume` هو الآن دالة تُرجع مثيلات format.constcream = Volume({ yell: true });console.dir(scream.transform({level: 'info', message: `آسف لجعلك تصرخ في رأسك!`},صرخة.options)); // {// المستوى: 'info'// message: 'آسف لأنك جعلتك تصرخ في رأسك!'// }// يمكن استخدام `الحجم` عدة مرات لإنشاء محتوى مختلف formats.const whisper = Volume({ whisper: true });console.dir(whisper.transform({level: 'info', message: `لماذا يجعلوننا نصرخ كثيرًا!`}, whisper.options)); // {// المستوى: 'معلومات'// الرسالة: 'لماذا يجعلوننا نصرخ كثيرًا!'// }
تتوافق مستويات التسجيل في winston
مع ترتيب الخطورة المحدد بواسطة RFC5424: يُفترض أن خطورة جميع المستويات تصاعدية رقميًا من الأكثر أهمية إلى الأقل أهمية.
يتم إعطاء كل level
أولوية عددية محددة. كلما زادت الأولوية، زادت أهمية الرسالة، وانخفضت الأولوية الصحيحة المقابلة. على سبيل المثال، كما هو محدد تمامًا في RFC5424، يتم تحديد أولويات مستويات syslog
من 0 إلى 7 (من الأعلى إلى الأدنى).
{الطوارئ: 0، التنبيه: 1، النقطة الحرجة: 2، الخطأ: 3، التحذير: 4، الإشعار: 5، المعلومات: 6، التصحيح: 7}
وبالمثل، يتم تحديد أولويات مستويات تسجيل npm
من 0 إلى 6 (من الأعلى إلى الأدنى):
{ خطأ: 0، تحذير: 1، معلومات: 2، http: 3، مطول: 4، تصحيح: 5، سخيف: 6}
إذا لم تحدد بوضوح المستويات التي يجب أن يستخدمها winston
، فسيتم استخدام مستويات npm
أعلاه.
يمكن ضبط مستوى رسالة التسجيل الخاصة بك بإحدى طريقتين. يمكنك تمرير سلسلة تمثل مستوى التسجيل إلى طريقة log () أو استخدام أساليب المستوى المحدد المحددة في كل Winston Logger.
//// أي مثيل مسجل//logger.log('silly', "127.0.0.1 - لا يوجد مكان مثل المنزل");logger.log('debug', "127.0.0.1 - لا يوجد مكان مثل المنزل") ;logger.log('verbose', "127.0.0.1 - لا يوجد مكان مثل المنزل");logger.log('info', "127.0.0.1 - لا يوجد مكان مثل المنزل");logger.log('warn', "127.0.0.1 - لا يوجد مكان مثل المنزل");logger.log('error', "127.0.0.1 - لا يوجد مكان مثل المنزل");logger.info("127.0.0.1 - لا يوجد مكان مثل home");logger.warn("127.0.0.1 - لا يوجد مكان مثل المنزل");logger.error("127.0.0.1 - لا يوجد مكان مثل المنزل");//// المسجل الافتراضي//winston.log( 'info', "127.0.0.1 - لا يوجد مكان مثل المنزل");winston.info("127.0.0.1 - لا يوجد مكان مثل المنزل");winston.info("127.0.0.1 - لا يوجد مكان مثل المنزل");winston.info("127.0.0.1 - لا يوجد مكان مثل المنزل");winston.info("127.0.0.1 - لا يوجد مكان مثل المنزل"); بيت")؛
يتيح لك winston
تحديد خاصية level
على كل عملية نقل والتي تحدد الحد الأقصى لمستوى الرسائل التي يجب على وسيلة النقل تسجيلها. على سبيل المثال، باستخدام مستويات syslog
، يمكنك فقط تسجيل رسائل error
إلى وحدة التحكم وكل info
وما يليها إلى ملف (والذي يتضمن رسائل error
):
const logger = Winston.createLogger({levels: Winston.config.syslog.levels, Transports: [new Winston.transports.Console({level: 'error' })، new Winston.transports.File({ filename: 'combined. سجل'، المستوى: 'معلومات' }) ]});
يمكنك أيضًا تغيير مستوى سجل النقل ديناميكيًا:
const Transports = { Console: new Winston.transports.Console({ المستوى: 'تحذير' })، الملف: new Winston.transports.File({ اسم الملف: 'combined.log'، المستوى: 'خطأ' })};const logger = Winston.createLogger({ Transports: [ Transports.console, Transports.file ]});logger.info('لن يتم تسجيل الدخول أيضًا النقل!');transports.console.level = 'info';transports.file.level = 'info';logger.info('سيتم تسجيل الدخول في كلتا عمليتي النقل!');
يدعم winston
مستويات تسجيل قابلة للتخصيص، حيث يتم ضبطها بشكل افتراضي على مستويات تسجيل نمط npm. يجب تحديد المستويات في وقت إنشاء المسجل الخاص بك.
بالإضافة إلى مستويات npm
و syslog
و cli
المحددة مسبقًا والمتوفرة في winston
، يمكنك أيضًا اختيار تحديد المستوى الخاص بك:
const myCustomLevels = { المستويات: { foo: 0، bar: 1، baz: 2، foobar: 3}، الألوان: { foo: 'blue'، bar: 'green'، baz: 'yellow'، foobar: 'red' }};const customLevelLogger = Winston.createLogger({ المستويات: myCustomLevels.levels});customLevelLogger.foobar('بعض رسائل مستوى foobar');
على الرغم من وجود تكرار بسيط في بنية البيانات هذه، إلا أنها تتيح تغليفًا بسيطًا إذا كنت لا تريد الحصول على ألوان. إذا كنت ترغب في الحصول على الألوان، بالإضافة إلى تمرير المستويات إلى المسجل نفسه، فيجب عليك إعلام وينستون بها:
Winston.addColors(myCustomLevels.colors);
يؤدي ذلك إلى تمكين المسجلين باستخدام منسق colorize
لتلوين مخرجات المستويات المخصصة وتصميمها بشكل مناسب.
بالإضافة إلى ذلك، يمكنك أيضًا تغيير لون الخلفية ونمط الخط. على سبيل المثال،
baz: 'أصفر مائل'، foobar: 'cyanBG أحمر غامق'
الخيارات الممكنة أدناه.
أنماط الخطوط: bold
، dim
، italic
، underline
، inverse
، hidden
، strikethrough
.
ألوان white
الأمامية: black
red
green
yellow
blue
magenta
cyan
gray
grey
.
ألوان الخلفية: blackBG
، redBG
، greenBG
، yellowBG
، blueBG
magentaBG
، cyanBG
، whiteBG
لتلوين مستوى التسجيل القياسي أضف
Winston.format.combine(winston.format.colorize(), Winston.format.simple());
حيث يكون winston.format.simple()
هو أي تنسيق آخر تريد استخدامه. يجب أن يأتي منسق colorize
قبل أي منسق يضيف النص الذي ترغب في تلوينه.
لتلوين سطر السجل الكامل باستخدام منسق json، يمكنك تطبيق ما يلي
Winston.format.combine( Winston.format.json(), Winston.format.colorize({ all: true }));
هناك العديد من وسائل النقل الأساسية المضمنة في winston
، والتي تستفيد من الشبكات المضمنة وإدخال/إخراج الملفات التي تقدمها Node.js الأساسية. بالإضافة إلى ذلك، هناك وسائل نقل إضافية كتبها أعضاء المجتمع.
من الممكن استخدام وسائل نقل متعددة من نفس النوع، على سبيل المثال، winston.transports.File
عند إنشاء عملية النقل.
مسجل const = Winston.createLogger({ وسائل النقل: [جديد Winston.transports.File({ اسم الملف: 'combined.log'، المستوى: 'info' })، new Winston.transports.File({ اسم الملف: 'errors.log' ، المستوى: 'خطأ' }) ]});
إذا أردت لاحقًا إزالة إحدى وسائل النقل هذه، فيمكنك القيام بذلك باستخدام وسيلة النقل نفسها. على سبيل المثال:
const CombinedLogs = logger.transports.find(transport => { return Transport.filename === 'combined.log'});logger.remove(combinedLogs);
من السهل إضافة وسيلة نقل مخصصة. كل ما عليك فعله هو قبول أي خيارات تحتاجها، وتنفيذ طريقة log()، واستهلاكها باستخدام winston
.
const Transport = require('winston-transport');const util = require('util');//// وراثة من `winston-transport` حتى تتمكن من الاستفادة // من الوظيفة الأساسية و`.exceptions.handle ()`.//module.exports = class YourCustomTransport Extends Transport { buildor(opts) { super(opts); // // استهلك أي خيارات مخصصة هنا. على سبيل المثال: // - معلومات الاتصال لقواعد البيانات // - معلومات المصادقة لواجهات برمجة التطبيقات (على سبيل المثال، logly، Papertrail، // logentries، وما إلى ذلك). // } log(info, callback) { setImmediate(() => { this.emit('logged', info); }); // إجراء الكتابة إلى رد اتصال الخدمة عن بعد () ؛ }};
نظرًا لأن كل وسيلة نقل ترث من Winston-transport، فمن الممكن تعيين تنسيق مخصص ومستوى سجل مخصص لكل وسيلة نقل على حدة:
const logger = Winston.createLogger({ Transports: [ new Winston.transports.File({ اسم الملف: 'error.log'، المستوى: 'خطأ'، التنسيق: Winston.format.json() })، new Winston.transports. Http({ المستوى: 'تحذير'، التنسيق: Winston.format.json() })، جديد Winston.transports.Console({ المستوى: 'معلومات'، التنسيق: Winston.format.combine(winston.format.colorize(),winston.format.simple() ) }) ]});
باستخدام winston
، من الممكن التقاط وتسجيل أحداث uncaughtException
من العملية الخاصة بك. باستخدام مثيل المسجل الخاص بك، يمكنك تمكين هذا السلوك عند إنشائه أو لاحقًا في دورة حياة التطبيقات الخاصة بك:
const { createLogger, Transports } = require('winston');// تمكين معالجة الاستثناءات عند إنشاء المسجل الخاص بك.const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ] ، ExceptionHandlers: [ new Transports.File({ filename: 'exceptions.log' }) ]});// أو قم بتمكينه لاحقًا عن طريق إضافة وسيلة نقل أو استخدام `.exceptions.handle`const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ]});// استدعاء Exceptions.handle مع وسيلة نقل للتعامل مع Exceptionslogger.exceptions.handle ( new Transports.File({ filename: 'exceptions.log' }));
إذا كنت تريد استخدام هذه الميزة مع المسجل الافتراضي، فما عليك سوى الاتصال بـ .exceptions.handle()
مع نسخة النقل.
//// يمكنك إضافة مسجل استثناء منفصل عن طريق تمريره إلى `.exceptions.handle`//winston.exceptions.handle( new Winston.transports.File({ filename: 'path/to/exceptions.log' }) );//// بدلاً من ذلك، يمكنك تعيين "handleExceptions" على "صحيح" عند إضافة وسائل النقل// إلى Winston.//winston.add(new Winston.transports.File({ اسم الملف: 'path/to/combined.log'، HandleExceptions: true}));
افتراضيًا، سيخرج Winston بعد تسجيل uncaughtException. إذا لم يكن هذا هو السلوك الذي تريده، فقم بتعيين exitOnError = false
const logger = Winston.createLogger({exitOnError: false });//// أو مثل هذا://logger.exitOnError = false;
عند العمل مع مثيلات المسجل المخصصة، يمكنك تمرير عمليات نقل منفصلة إلى خاصية exceptionHandlers
أو تعيين handleExceptions
على أي وسيلة نقل.
مسجل const = Winston.createLogger({ وسائل النقل: [ new Winston.transports.File({ اسم الملف: 'path/to/combined.log' }) ]، ExceptionHandlers: [ new Winston.transports.File({ اسم الملف: 'path/ to/exceptions.log' }) ]});
const logger = Winston.createLogger({ Transports: [ new Winston.transports.Console({ HandleExceptions: true }) ],exitOnError: false});
يمكن أن يكون خيار exitOnError
أيضًا وظيفة لمنع الخروج عند أنواع معينة فقط من الأخطاء:
وظيفة تجاهلEpipe(err) { return err.code !== 'EPIPE';}const logger = Winston.createLogger({exitOnError:ignoreEpipe });//// أو مثل هذا://logger.exitOnError =ignEpipe;
باستخدام winston
، من الممكن التقاط وتسجيل أحداث unhandledRejection
من العملية الخاصة بك. باستخدام مثيل المسجل الخاص بك، يمكنك تمكين هذا السلوك عند إنشائه أو لاحقًا في دورة حياة التطبيقات الخاصة بك:
const { createLogger, Transports } = require('winston');// تمكين معالجة الرفض عند إنشاء المسجل الخاص بك.const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ] ,رفضHandlers: [ new Transports.File({ filename: 'rejections.log' }) ]});// أو قم بتمكينه لاحقًا عن طريق إضافة وسيلة نقل أو استخدام `.rejections.handle`const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ]});// استدعاء الرفض. مقبض مع وسيلة نقل للتعامل مع الرفضlogger.rejections.handle ( new Transports.File({ filename: 'rejections.log' }));
إذا كنت تريد استخدام هذه الميزة مع المُسجل الافتراضي، فما عليك سوى الاتصال بـ .rejections.handle()
مع مثيل النقل.
//// يمكنك إضافة مسجل رفض منفصل عن طريق تمريره إلى `.rejections.handle`//winston.rejections.handle( new Winston.transports.File({ filename: 'path/to/rejections.log' }) );//// بدلاً من ذلك، يمكنك ضبط "handleRejections" على "صحيح" عند إضافة وسائل النقل// إلى Winston.//winston.add(new Winston.transports.File({ اسم الملف: 'path/to/combined.log'، HandleRejections: true}));
بالإضافة إلى تسجيل الرسائل والبيانات الوصفية، يمتلك winston
أيضًا آلية بسيطة لتحديد الملفات يتم تنفيذها لأي مسجل:
//// بدء الملف الشخصي لـ 'test'//logger.profile('test');setTimeout(function () { // // إيقاف الملف الشخصي لـ 'test'. سيتم الآن التسجيل: // '17 21 يناير :00:00 - معلومات: مدة الاختبار = 1000 مللي ثانية' // logger.profile('test');}, 1000);
يمكنك أيضًا بدء مؤقت والاحتفاظ بمرجع يمكنك الاتصال به .done()
على:
// إرجاع كائن يتوافق مع توقيت محدد. عند الانتهاء من // يتم الاتصال، سينتهي المؤقت ويسجل المدة. على سبيل المثال: // ملف تعريف const = logger.startTimer(); setTimeout(function () { Profiler.done({ message: 'Logging message' }); }, 1000);
يتم تعيين كافة رسائل الملف الشخصي على مستوى "المعلومات" بشكل افتراضي، وتكون كل من الرسالة والبيانات التعريفية اختيارية. بالنسبة لرسائل الملفات الشخصية الفردية، يمكنك تجاوز مستوى السجل الافتراضي عن طريق توفير كائن بيانات التعريف بخاصية level
:
logger.profile('test', {level: 'debug' });
يدعم winston
الاستعلام عن السجلات باستخدام خيارات تشبه Loggly. راجع واجهة برمجة تطبيقات البحث Logly. على وجه التحديد: File
و Couchdb
و Redis
و Loggly
و Nssocket
و Http
.
خيارات const = { from: new Date() - (24 * 60 * 60 * 1000)، حتى: new Date()، الحد: 10، البدء: 0، الترتيب: 'desc'، الحقول: ['message']} ;//// ابحث عن العناصر التي تم تسجيلها بين اليوم والأمس.//logger.query(options, function (err, results) { if (err) { /* TODO: Handle me */ throw err; } console.log(results);});
يتيح لك البث دفق السجلات الخاصة بك مرة أخرى من وسيلة النقل التي اخترتها.
//// ابدأ من النهاية.//winston.stream({ start: -1 }).on('log', function(log) { console.log(log);});
يمكن الوصول إلى المُسجل الافتراضي من خلال وحدة winston
مباشرةً. تتوفر أي طريقة يمكنك استدعاؤها على مثيل المسجل على المسجل الافتراضي:
const Winston = require('winston');winston.log('info', 'مرحبًا بملفات السجل الموزعة!');winston.info('مرحبًا مرة أخرى بالسجلات الموزعة');winston.level = 'debug';winston.log ("debug"، "الآن تمت كتابة رسائل تصحيح الأخطاء الخاصة بي إلى وحدة التحكم!")؛
بشكل افتراضي، لا يتم تعيين أي وسائل نقل على المسجل الافتراضي. يجب عليك إضافة وسائل النقل أو إزالتها عبر التابعين add()
و remove()
:
ملفات const = new Winston.transports.File({ filename: 'combined.log' });const console = new Winston.transports.Console();winston.add(console);winston.add(files);winston.remove (وحدة التحكم)؛
أو قم بذلك بمكالمة واحدة للتكوين ():
Winston.configure({ وسائل النقل: [ new Winston.transports.File({ filename: 'somefile.log' }) ]});
لمزيد من الوثائق حول العمل مع كل وسيلة نقل فردية تدعمها winston
راجع مستند winston
Transports.
winston
غالبًا ما يكون من المفيد الانتظار حتى تتم كتابة سجلاتك قبل الخروج من العملية. كل مثيل لـ winston.Logger
هو أيضًا [دفق Node.js]. سيتم رفع حدث finish
عندما يتم مسح كافة السجلات إلى جميع وسائل النقل بعد انتهاء الدفق.
const Transport = new Winston.transports.Console();const logger = Winston.createLogger({ Transports: [transport]});logger.on('finish', function (info) { // تحتوي جميع رسائل سجل `info` على تم تسجيل الدخول الآن});logger.info('CHILL WINSTON!', { بجدية: صحيح });logger.end();
ومن الجدير بالذكر أيضًا أن المُسجل يُصدر أيضًا حدث "خطأ" إذا حدث خطأ داخل المُسجل نفسه والذي يجب عليك معالجته أو منعه إذا كنت لا تريد استثناءات غير مُعالَجة:
//// معالجة الأخطاء الناشئة في المسجل نفسه//logger.on('error', function (err) { /* Do Something */ });
في كثير من الأحيان، في التطبيقات الأكبر حجمًا والأكثر تعقيدًا، من الضروري أن يكون لديك مثيلات متعددة للمسجل بإعدادات مختلفة. كل مسجل مسؤول عن منطقة (أو فئة) ميزات مختلفة. تم الكشف عن هذا في winston
بطريقتين: من خلال winston.loggers
ومثيلات winston.Container
. في الواقع، winston.loggers
هو مجرد مثيل محدد مسبقًا لـ winston.Container
:
const Winston = require('winston');const { format } = Winston;const { Combine, label, json } = format;//// تكوين المسجل لـ `category1`//winston.loggers.add('category1' ، { التنسيق: دمج (التسمية ({ التسمية: 'الفئة الأولى' })، json ())، وسائل النقل: [new Winston.transports.Console ({ المستوى: 'سخيف' }), new Winston.transports.File({ filename: 'somefile.log' }) ]});//// تكوين المسجل لـ `category2`//winston.loggers.add('category2', { format: الجمع بين (التسمية ({ التسمية: 'الفئة الثانية' })، json ())، النقل: [جديد Winston.transports.Http ({ المضيف: 'المضيف المحلي'، المنفذ:8080 }) ]});
الآن بعد أن تم إعداد أدوات تسجيل الدخول، يمكنك طلب Winston في أي ملف في تطبيقك والوصول إلى أدوات تسجيل البيانات هذه التي تم تكوينها مسبقًا:
const Winston = require('winston');//// احصل على أدوات التسجيل التي تم تكوينها مسبقًا //const Category1 = Winston.loggers.get('category1');const Category2 = Winston.loggers.get('category2');category1. info('تسجيل الدخول إلى الملفات وعمليات نقل وحدة التحكم');category2.info('تسجيل الدخول إلى نقل http');
إذا كنت تفضل إدارة Container
بنفسك، فيمكنك ببساطة إنشاء مثيل لها:
const Winston = require('winston');const {format } = Winston;const { Combine, label, json } = format;const Container = new Winston.Container();container.add('category1', {format: Combine ( التسمية ({ التسمية: 'الفئة الأولى' })، json ())، وسائل النقل: [جديد Winston.transports.Console ({ المستوى: 'سخيفة' })، جديد Winston.transports.File({ filename: 'somefile.log' }) ]});const class1 = Container.get('category1');category1.info('تسجيل الدخول إلى الملف وعمليات نقل وحدة التحكم');
بشكل افتراضي، يرسل النقل winston.transports.Console
رسائل إلى stdout
و stderr
. وهذا أمر جيد في معظم الحالات؛ ومع ذلك، هناك بعض الحالات التي لا يكون فيها ذلك مرغوبًا، بما في ذلك:
تصحيح الأخطاء باستخدام VSCode والإرفاق بعملية Node.js بدلاً من تشغيلها
كتابة رسائل بتنسيق JSON في AWS Lambda
التسجيل أثناء اختبارات Jest باستخدام الخيار --silent
لجعل سجل النقل يستخدم console.log()
و console.warn()
و console.error()
بدلاً من ذلك، اضبط خيار forceConsole
على true
:
const logger = Winston.createLogger({level: 'info', Transports: [new Winston.transports.Console({ forceConsole: true })]});
npm تثبيت ونستون
الغزل إضافة ونستون
جميع اختبارات ونستون مكتوبة باستخدام mocha
و nyc
و assume
. يمكن تشغيلها باستخدام npm
.
اختبار npm