คนตัดไม้สำหรับเกือบทุกอย่าง
ดูคู่มือการอัพเกรดสำหรับข้อมูลเพิ่มเติม รายงานข้อผิดพลาดและประชาสัมพันธ์ยินดีต้อนรับ!
[email protected]
ใช่ไหม โปรดทราบว่าเอกสารด้านล่างมีไว้สำหรับ winston@3
อ่านเอกสาร [email protected]
winston
ได้รับการออกแบบให้เป็นไลบรารีการบันทึกที่เรียบง่ายและเป็นสากล พร้อมรองรับการขนส่งหลายรายการ การขนส่งโดยพื้นฐานแล้วเป็นอุปกรณ์จัดเก็บข้อมูลสำหรับบันทึกของคุณ ตัวบันทึก winston
แต่ละตัวสามารถมีการขนส่งหลายรายการ (ดู: การขนส่ง) ที่กำหนดค่าในระดับที่แตกต่างกัน (ดู: ระดับการบันทึก) ตัวอย่างเช่น เราอาจต้องการให้บันทึกข้อผิดพลาดถูกจัดเก็บไว้ในตำแหน่งระยะไกลถาวร (เช่น ฐานข้อมูล) แต่บันทึกทั้งหมดจะส่งออกไปยังคอนโซลหรือไฟล์ในเครื่อง
winston
มีเป้าหมายที่จะแยกส่วนต่างๆ ของกระบวนการบันทึกเพื่อให้มีความยืดหยุ่นและขยายได้มากขึ้น มีการให้ความสำคัญกับการสนับสนุนความยืดหยุ่นในการจัดรูปแบบบันทึก (ดู: รูปแบบ) และระดับ (ดู: การใช้ระดับการบันทึกแบบกำหนดเอง) และสร้างความมั่นใจว่า API เหล่านั้นแยกออกจากการใช้งานการบันทึกการขนส่ง (เช่น วิธีจัดเก็บ / จัดทำดัชนีบันทึก โปรดดู: การเพิ่มแบบกำหนดเอง การขนส่ง) ไปยัง API ที่พวกเขาเปิดเผยต่อโปรแกรมเมอร์
TL;DR? ดูตัวอย่างการเริ่มต้นอย่างรวดเร็วใน ./examples/
/ มีตัวอย่างอื่นๆ อีกมากมายใน . ./examples/*.js
ไม่เห็นตัวอย่างที่คุณคิดว่าควรมีใช่หรือไม่ ส่งคำขอดึงเพื่อเพิ่ม!
วิธีที่แนะนำในการใช้ winston
คือการสร้างเครื่องบันทึกของคุณเอง วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการใช้ winston.createLogger
:
const winston = need('winston');const logger = winston.createLogger({ ระดับ: 'ข้อมูล', รูปแบบ: winston.format.json(), defaultMeta: { บริการ: 'บริการผู้ใช้' }, การขนส่ง: [ / / // - เขียนบันทึกทั้งหมดที่มีระดับความสำคัญของ `ข้อผิดพลาด` หรือสูงกว่า ถึง `error.log` // (เช่น ข้อผิดพลาด ร้ายแรง แต่ไม่ใช่ระดับอื่น) // new winston.transports.File({ ชื่อไฟล์: 'error.log', ระดับ: 'error' }), // // - เขียนบันทึกทั้งหมดที่มีระดับความสำคัญ `ข้อมูล` หรือสูงกว่าถึง `combined.log` // (เช่น ร้ายแรง ข้อผิดพลาด คำเตือน และข้อมูล แต่ไม่ได้ติดตาม) // new winston.transports.File({ filename: 'combined.log' }), ],});//// หากเราไม่ได้อยู่ในการใช้งานจริง ให้เข้าสู่ `console` ด้วย รูปแบบ::// `${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
การสร้างรูปแบบที่กำหนดเอง
ระดับการบันทึก
การใช้ระดับการบันทึก
การใช้ระดับการบันทึกแบบกำหนดเอง
การขนส่ง
การขนส่งหลายประเภทประเภทเดียวกัน
การเพิ่มการขนส่งแบบกำหนดเอง
ตัวเลือกการขนส่งทั่วไป
ข้อยกเว้น
การจัดการข้อยกเว้น Uncaught ด้วย winston
จะออกหรือไม่ออก
การปฏิเสธ
การจัดการกับการปฏิเสธสัญญาที่ไม่ได้รับการตรวจสอบกับวินสตัน
การทำโปรไฟล์
บันทึกการสตรีม
กำลังค้นหาบันทึก
อ่านต่อ
การใช้ตัวบันทึกเริ่มต้น
กำลังรอบันทึกที่จะเขียนใน winston
การทำงานกับ Loggers หลายคนใน winston
การกำหนดเส้นทางข้อความขนส่งคอนโซลไปยังคอนโซลแทน stdout และ stderr
การติดตั้ง
เรียกใช้การทดสอบ
ระดับการบันทึกใน winston
เป็นไปตามลำดับความรุนแรงที่ระบุโดย RFC5424: ความรุนแรงของทุกระดับจะถือว่า เพิ่มขึ้น เป็นตัวเลขจากสำคัญที่สุดไปสำคัญน้อยที่สุด
ระดับ const = { ข้อผิดพลาด: 0 เตือน: 1 ข้อมูล: 2 http: 3 รายละเอียด: 4 ดีบัก: 5 โง่: 6};
คุณเริ่มต้นด้วยการสร้างคนตัดไม้โดยใช้ winston.createLogger
:
const logger = winston.createLogger({ การขนส่ง: [ new winston.transports.Console(), winston.transports.File ใหม่ ({ ชื่อไฟล์: '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({ ระดับ: 'ข้อมูล' ข้อความ: 'สวัสดีไฟล์บันทึกที่แจกจ่าย!'});logger.info('สวัสดีบันทึกที่แจกจ่ายอีกครั้ง');
คุณสามารถเพิ่มหรือลบการขนส่งออกจาก logger
เมื่อได้รับจาก winston.createLogger
:
ไฟล์ const = new winston.transports.File({ ชื่อไฟล์: 'combined.log' });const console = new winston.transports.Console();logger .clear() // ลบการขนส่งทั้งหมด .add(console) // เพิ่มการขนส่งคอนโซล .add(files) // เพิ่มการขนส่งไฟล์ .remove(console); // ลบการขนส่งคอนโซล
คุณยังสามารถกำหนดค่าอินสแตนซ์ winston.Logger
ใหม่ได้โดยใช้วิธี configure
:
const logger = winston.createLogger ({ ระดับ: 'ข้อมูล' การขนส่ง: [ ใหม่ winston.transports.Console (), winston.transports.File ใหม่ ({ ชื่อไฟล์: 'combined.log' }) ]});/// / แทนที่การขนส่งก่อนหน้านี้ด้วยการขนส่งใน// การกำหนดค่าใหม่ขายส่ง//const DailyRotateFile = need('winston-daily-rotate-file');logger.configure({ ระดับ: 'verbose' การขนส่ง: [ new DailyRotateFile(opts) ]});
คุณสามารถสร้างตัวบันทึกย่อยจากตัวบันทึกที่มีอยู่เพื่อส่งต่อการแทนที่ข้อมูลเมตา:
const logger = winston.createLogger({ การขนส่ง: [ ใหม่ 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 = { ระดับ: 'ข้อมูล', // ระดับของข้อความบันทึก: 'เฮ้! บันทึกอะไรบางอย่าง? // ข้อความอธิบายกำลังถูกบันทึกไว้};
คุณสมบัติ นอกเหนือจากระดับและข้อความ ถือเป็น " meta
" เช่น:
const { ระดับ, ข้อความ, ...meta } = ข้อมูล;
หลายรูปแบบใน 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 { ระดับ, ข้อความ, SPLAT } = ต้องการ ('triple-beam');console.log (LEVEL === Symbol.for ('level')); // trueconsole.log (MESSAGE === Symbol.for ( 'ข้อความ'));// trueconsole.log(SPLAT === Symbol.for('splat'));// จริง
หมายเหตุ: คุณสมบัติ
{ message }
ใด ๆ ในmeta
ออบเจ็กต์ที่ให้ไว้จะถูกต่อเข้ากับmsg
ใด ๆ ที่ให้ไว้แล้วโดยอัตโนมัติ ตัวอย่างเช่น ด้านล่างจะเชื่อม 'world' เข้ากับ 'hello':logger.log('error', 'hello', { ข้อความ: 'world' }); logger.info('hello', { ข้อความ: 'world' });
สามารถเข้าถึงรูปแบบใน winston
ได้จาก winston.format
พวกมันถูกนำไปใช้ใน logform
ซึ่งเป็นโมดูลแยกต่างหากจาก winston
สิ่งนี้ให้ความยืดหยุ่นเมื่อเขียนการขนส่งของคุณเอง ในกรณีที่คุณต้องการรวมรูปแบบเริ่มต้นให้กับการขนส่งของคุณ
ในเวอร์ชันสมัยใหม่ของสตริงเทมเพลต node
มีประสิทธิภาพมากและเป็นวิธีที่แนะนำสำหรับการจัดรูปแบบผู้ใช้ปลายทางส่วนใหญ่ หากคุณต้องการจัดรูปแบบบันทึกของคุณตามความต้องการ winston.format.printf
เหมาะสำหรับคุณ:
const { createLogger, รูปแบบ, การขนส่ง } = ต้องการ ('winston'); const { รวม, การประทับเวลา, ป้ายกำกับ, printf } = รูปแบบ; const myFormat = printf (({ ระดับ, ข้อความ, ป้ายกำกับ, การประทับเวลา }) => { return ` ${timestamp} [${label}] ${level}: ${message}`;});const logger = createLogger({ รูปแบบ: รวม( label({ label: 'right meow!' }), การประทับเวลา (), myFormat ), การขนส่ง: [new Transports.Console()]});
หากต้องการดูว่ามีรูปแบบในตัวใดบ้างและเรียนรู้เพิ่มเติมเกี่ยวกับการสร้างรูปแบบการบันทึกที่คุณกำหนดเอง โปรดดูที่ logform
สามารถรวมรูปแบบจำนวนเท่าใดก็ได้เป็นรูปแบบเดียวโดยใช้ format.combine
เนื่องจาก format.combine
ไม่มี opts
เพื่อความสะดวกจึงส่งคืนอินสแตนซ์ที่สร้างไว้ล่วงหน้าของรูปแบบรวม
const { createLogger, รูปแบบ, การขนส่ง } = ต้องการ ('winston'); const { รวม, การประทับเวลา, ป้ายกำกับ, PrettyPrint } = รูปแบบ; const logger = createLogger ({ รูปแบบ: รวม ( label ({ label: 'right meow!' } ), การประทับเวลา(), PrettyPrint() ), การขนส่ง: [new Transports.Console()]})logger.log({ ระดับ: 'info', ข้อความ: 'การทดสอบคือเวลาใด ที่?'});// Outputs:// { ระดับ: 'ข้อมูล',// ข้อความ: 'การทดสอบเวลาเท่าไร',// ป้ายกำกับ: 'ใช่เหมียว!',// การประทับเวลา: '2017- 09-30T03:57:26.875Z' }
วิธี log
จัดให้มีการแก้ไขสตริงโดยใช้ util.format ต้องเปิดใช้งานโดยใช้ format.splat()
ด้านล่างนี้คือตัวอย่างที่กำหนดรูปแบบด้วยการแก้ไขสตริงข้อความโดยใช้ format.splat
จากนั้นจึงทำให้ข้อความ info
เป็นอนุกรมโดยใช้ format.simple
const { createLogger, รูปแบบ, การขนส่ง } = ต้องการ ('winston'); const logger = createLogger ({ รูปแบบ: format.combine ( format.splat (), format.simple () ), การขนส่ง: [การขนส่งใหม่.Console () ]});// info: ทดสอบข้อความสตริงของฉัน {}logger.log('info', 'test message %s', 'my string');// info: ทดสอบข้อความ 123 {}logger.log('info', 'test message %d', 123);// info: ทดสอบข้อความวินาทีแรก {number: 123}logger.log('info', 'test message %s, %s' , 'ครั้งแรก', 'วินาที', { หมายเลข: 123 });
info
หากคุณต้องการกรองออบเจ็กต์ info
ที่ระบุออกทั้งหมดเมื่อทำการบันทึก ให้ส่งคืนค่าที่ผิดพลาด
const { createLogger, รูปแบบ, การขนส่ง } = ต้องการ ('winston'); // ละเว้นข้อความบันทึกหากมี { ส่วนตัว: จริง } const allowancePrivate = รูปแบบ ((ข้อมูล, ตัวเลือก) => { ถ้า (info.private) { กลับ false; } ข้อมูลส่งคืน;}); const logger = createLogger({ format: format.combine(ignonPrivate(), format.json() ), การขนส่ง: [ใหม่ Transports.Console()]});// ผลลัพธ์: {"level": "ข้อผิดพลาด" "ข้อความ" "ข้อผิดพลาดสาธารณะในการแบ่งปัน"} logger.log ({ ระดับ: 'ข้อผิดพลาด' ข้อความ: 'ข้อผิดพลาดสาธารณะถึง share'});// ข้อความที่มี { private: true } จะไม่ถูกเขียนเมื่อ logged.logger.log({ private: true, ระดับ: 'error', ข้อความ: 'นี่เป็นความลับสุดยอด - ซ่อนมันไว้'}) ;
การใช้ format.combine
จะเคารพค่าเท็จที่ส่งกลับและหยุดการประเมินรูปแบบที่ตามมาในซีรีส์ ตัวอย่างเช่น:
const { format } = need('winston');const { รวม, การประทับเวลา, ป้ายกำกับ } = format;const willNeverThrow = format.combine( format(info => { return false })(), // ละเว้นทุกรูปแบบ (ข้อมูล => { Throw new Error('ไม่เคยถึง') })());
รูปแบบคือออบเจ็กต์ต้นแบบ (เช่น อินสแตนซ์ของคลาส) ที่กำหนดวิธีการเดียว: transform(info, opts)
และส่งคืน info
ที่กลายพันธุ์ :
info
: วัตถุที่แสดงถึงข้อความบันทึก
opts
: การตั้งค่าเฉพาะสำหรับอินสแตนซ์ปัจจุบันของรูปแบบ
พวกเขาคาดว่าจะส่งคืนหนึ่งในสองสิ่ง:
วัตถุ info
ที่แสดงถึงอาร์กิวเมนต์ info
ที่แก้ไข การอ้างอิงออบเจ็กต์ไม่จำเป็นต้องถูกรักษาไว้ หากต้องการความไม่เปลี่ยนรูป รูปแบบบิวท์อินในปัจจุบันทั้งหมดถือว่า info
ไม่แน่นอน แต่ [immutablejs] กำลังได้รับการพิจารณาสำหรับการเปิดตัวในอนาคต
ค่าเท็จ ที่บ่งชี้ว่าอาร์กิวเมนต์ info
ควรถูกละเว้นโดยผู้โทร (ดู: การกรองออบเจ็กต์ info
) ด้านล่าง
winston.format
ได้รับการออกแบบให้เรียบง่ายที่สุด หากต้องการกำหนดรูปแบบใหม่ เพียงส่งฟังก์ชัน transform(info, opts)
เพื่อรับ Format
ใหม่
Format
ที่มีชื่อที่ส่งคืนสามารถใช้เพื่อสร้างสำเนาของ Format
ที่กำหนดได้มากเท่าที่ต้องการ:
const { format } = need('winston');const volume = format((info, opts) => { if (opts.yell) { info.message = info.message.toUpperCase(); } else if (opts. กระซิบ) { info.message = info.message.toLowerCase(); } return info;});// `volume` ตอนนี้เป็นฟังก์ชันที่ส่งคืนอินสแตนซ์ของเสียงกรีดร้อง format.const = ปริมาณ({ yell: true });console.dir(scream.transform({ ระดับ: 'info', ข้อความ: `ขออภัยที่ทำให้คุณตะโกนในหัว!`},กรีดร้อง.options));// {/ / ระดับ: 'ข้อมูล'// ข้อความ: 'ขออภัยที่ทำให้คุณตะโกนในหัวของคุณ!'// }// `volume` สามารถนำมาใช้หลายครั้งเพื่อสร้างรูปแบบที่แตกต่างกัน const กระซิบ = ปริมาณ ({ กระซิบ: จริง });console.dir(whisper.transform({ ระดับ: 'ข้อมูล', ข้อความ: `ทำไมพวกเขาถึงทำให้เราตะโกนมาก!`}, กระซิบตัวเลือก)); // {// ระดับ: ' info'// ข้อความ: 'ทำไมพวกเขาถึงทำให้เราตะโกนมาก!'// }
ระดับการบันทึกใน winston
เป็นไปตามลำดับความรุนแรงที่ระบุโดย RFC5424: ความรุนแรงของทุกระดับจะถือว่า เพิ่มขึ้น เป็นตัวเลขจากสำคัญที่สุดไปสำคัญน้อยที่สุด
แต่ละ level
จะได้รับลำดับความสำคัญจำนวนเต็มเฉพาะ ยิ่งลำดับความสำคัญสูงเท่าใด ข้อความก็จะยิ่งมีความสำคัญมากขึ้นเท่านั้น และลำดับความสำคัญของจำนวนเต็มที่สอดคล้องกันก็จะยิ่งต่ำลง ตัวอย่างเช่น ตามที่ระบุไว้ทุกประการใน RFC5424 ระดับ syslog
จะถูกจัดลำดับความสำคัญตั้งแต่ 0 ถึง 7 (สูงสุดไปต่ำสุด)
{ เกิดขึ้น: 0, การแจ้งเตือน: 1, crit: 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 - ไม่มีที่ไหนเหมือนบ้าน");logger.warn("127.0.0.1 - ไม่มีที่ไหนเหมือนบ้าน"); home");logger.error("127.0.0.1 - ไม่มีที่ไหนเหมือนบ้าน");//// Default logger//winston.log('info', "127.0.0.1 - ไม่มีที่ไหนเหมือนบ้าน"); winston.info("127.0.0.1 - ไม่มีที่ไหนเหมือนบ้าน");
winston
อนุญาตให้คุณกำหนดคุณสมบัติ level
ในแต่ละการขนส่งซึ่งระบุระดับ สูงสุด ของข้อความที่การขนส่งควรบันทึก ตัวอย่างเช่น การใช้ระดับ syslog
คุณสามารถบันทึกเฉพาะข้อความ error
ไปยังคอนโซลและ info
ทุกอย่างและด้านล่างลงในไฟล์ (ซึ่งรวมถึงข้อความแสดง error
):
const logger = winston.createLogger ({ ระดับ: winston.config.syslog.levels, การขนส่ง: [ ใหม่ winston.transports.Console ({ ระดับ: 'ข้อผิดพลาด' }), winston.transports.File ใหม่ ({ ชื่อไฟล์: 'combined. บันทึก', ระดับ: 'ข้อมูล' }) ]});
คุณยังอาจเปลี่ยนระดับบันทึกของการขนส่งแบบไดนามิกได้:
const Transports = { คอนโซล: new winston.transports.Console ({ ระดับ: 'warn' }), ไฟล์: new winston.transports.File ({ ชื่อไฟล์: 'combined.log', ระดับ: 'error' })}; const logger = winston.createLogger({ การขนส่ง: [ Transports.console, Transports.file ]}); logger.info ('จะไม่ถูกเข้าสู่ระบบเช่นกัน Transport!');transports.console.level = 'info';transports.file.level = 'info';logger.info('จะถูกบันทึกไว้ในการขนส่งทั้งสอง!');
winston
รองรับระดับการบันทึกที่ปรับแต่งได้ โดยค่าเริ่มต้นเป็นระดับการบันทึกสไตล์ npm ต้องระบุระดับในขณะที่สร้างเครื่องบันทึกของคุณ
นอกจากระดับ npm
, syslog
และ cli
ที่กำหนดไว้ล่วงหน้าที่มีอยู่ใน winston
แล้ว คุณยังสามารถเลือกที่จะกำหนดระดับของคุณเองได้:
const myCustomLevels = { ระดับ: { foo: 0, บาร์: 1, baz: 2, foobar: 3 }, สี: { foo: 'blue', แถบ: 'สีเขียว', baz: 'สีเหลือง', foobar: 'สีแดง' }};const customLevelLogger = winston.createLogger({ ระดับ: myCustomLevels.levels});customLevelLogger.foobar('บางส่วน ข้อความระดับ foobar');
แม้ว่าโครงสร้างข้อมูลนี้จะซ้ำกันเล็กน้อย แต่ก็ทำให้สามารถห่อหุ้มได้ง่าย หากคุณไม่ต้องการให้มีสี หากคุณต้องการที่จะมีสี นอกเหนือจากการส่งผ่านระดับต่างๆ ให้กับ Logger แล้ว คุณต้องแจ้งให้ Winston ทราบด้วย:
winston.addColors(myCustomLevels.colors);
ซึ่งช่วยให้ผู้บันทึกที่ใช้ตัวจัดรูป colorize
สามารถปรับสีและจัดรูปแบบเอาต์พุตของระดับที่กำหนดเองได้อย่างเหมาะสม
นอกจากนี้คุณยังสามารถเปลี่ยนสีพื้นหลังและรูปแบบตัวอักษรได้อีกด้วย ตัวอย่างเช่น,
baz: 'ตัวเอียงสีเหลือง', foobar: 'สีฟ้าตัวหนาสีแดง cyanBG'
ตัวเลือกที่เป็นไปได้อยู่ด้านล่าง
รูปแบบตัวอักษร: bold
, dim
, italic
, underline
, inverse
, hidden
, strikethrough
สีพื้นหน้าของแบบอักษร: black
, red
, green
, yellow
, น้ำเงิน gray
magenta
blue
, ฟ้า , cyan
, white
, 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({ ทั้งหมด: จริง }));
มีการขนส่งหลักหลายรายการรวมอยู่ใน winston
ซึ่งใช้ประโยชน์จากระบบเครือข่ายในตัวและ I/O ไฟล์ที่นำเสนอโดยแกนหลัก Node.js นอกจากนี้ยังมีการขนส่งเพิ่มเติมที่เขียนโดยสมาชิกของชุมชน
คุณสามารถใช้การขนส่งประเภทเดียวกันหลายรายการได้ เช่น winston.transports.File
เมื่อคุณสร้างการขนส่ง
const logger = winston.createLogger ({ การขนส่ง: [ ใหม่ winston.transports.File ({ ชื่อไฟล์: 'combined.log', ระดับ: 'ข้อมูล' }), winston.transports.File ใหม่ ({ ชื่อไฟล์: 'errors.log' , ระดับ: 'ข้อผิดพลาด' }) ]});
หากคุณต้องการลบการขนส่งเหล่านี้ออกในภายหลัง คุณสามารถทำได้โดยใช้การขนส่งนั้นเอง เช่น:
const integratedLogs = logger.transports.find (ขนส่ง => { return Transport.filename === 'combined.log'}); logger.remove (combinedLogs);
การเพิ่มการขนส่งแบบกำหนดเองเป็นเรื่องง่าย สิ่งที่คุณต้องทำคือยอมรับตัวเลือกใดๆ ที่คุณต้องการ ใช้เมธอด log() และใช้มันกับ winston
const Transport = need('winston-transport');const util = need('util');//// สืบทอดจาก `winston-transport` เพื่อให้คุณสามารถใช้ประโยชน์จาก // ของฟังก์ชันพื้นฐานและ `.Exceptions.handle ()`.//module.exports = class YourCustomTransport ขยาย Transport { ตัวสร้าง (opts) { super (opts); // // ใช้ตัวเลือกที่กำหนดเองใดๆ ที่นี่ เช่น: // - ข้อมูลการเชื่อมต่อสำหรับฐานข้อมูล // - ข้อมูลการตรวจสอบสิทธิ์สำหรับ API (เช่น loggly, papertrail, // logentries ฯลฯ) // } log(ข้อมูล, โทรกลับ) { setImmediate(() => { this.emit('logged', info); }); // ทำการเขียนไปยังการเรียกกลับบริการระยะไกล (); -
เนื่องจากการขนส่งทุกครั้งสืบทอดมาจาก winston-transport คุณจึงสามารถตั้งค่ารูปแบบที่กำหนดเองและระดับบันทึกที่กำหนดเองในแต่ละการขนส่งแยกกัน:
const logger = winston.createLogger({ การขนส่ง: [ new winston.transports.File({ ชื่อไฟล์: 'error.log', ระดับ: 'error', รูปแบบ: winston.format.json() }), winston.transports ใหม่ Http ({ ระดับ: 'คำเตือน' รูปแบบ: winston.format.json() }) ใหม่ winston.transports.Console ({ ระดับ: 'ข้อมูล' รูปแบบ: winston.format.combine( winston.format.colorize(), winston.format.simple() ) }) ]});
ด้วย winston
คุณสามารถตรวจจับและบันทึกเหตุการณ์ uncaughtException
จากกระบวนการของคุณได้ ด้วยอินสแตนซ์ตัวบันทึกของคุณเอง คุณสามารถเปิดใช้งานลักษณะการทำงานนี้ได้เมื่อถูกสร้างขึ้นหรือเปิดใช้งานในภายหลังในวงจรการใช้งานแอปพลิเคชันของคุณ:
const { createLogger, Transports } = need('winston');// เปิดใช้งานการจัดการข้อยกเว้นเมื่อคุณสร้าง logger.const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ] , ข้อยกเว้นตัวจัดการ: [ new Transports.File({ filename: 'Exceptions.log' }) ]});// หรือเปิดใช้งานในภายหลังโดยการเพิ่มการขนส่งหรือใช้ `.Exceptions.handle`const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ]});// เรียกExceptions.handleด้วยการขนส่งเพื่อจัดการExceptionslogger.Exceptions.handle ( Transports.File ใหม่ ({ ชื่อไฟล์: 'ข้อยกเว้น.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 logger = winston.createLogger ({ การขนส่ง: [ ใหม่ winston.transports.File ({ ชื่อไฟล์: 'path/to/combined.log' }) ], ข้อยกเว้นตัวจัดการ: [ ใหม่ winston.transports.File ({ ชื่อไฟล์: 'path/ ถึง/ข้อยกเว้น.log' }) ]});
const logger = winston.createLogger ({ การขนส่ง: [ ใหม่ winston.transports.Console ({ handleExceptions: true }) ], exitOnError: false});
ตัวเลือก exitOnError
ยังสามารถเป็นฟังก์ชันเพื่อป้องกันการออกจากข้อผิดพลาดบางประเภทเท่านั้น:
function IgnEpipe(err) { return err.code !== 'EPIPE';} const logger = winston.createLogger({ exitOnError: IgnEpipe });//// หรือเช่นนี้: //logger.exitOnError = IgnEpipe;
ด้วย winston
คุณสามารถตรวจจับและบันทึกเหตุการณ์ unhandledRejection
จากกระบวนการของคุณ ด้วยอินสแตนซ์ตัวบันทึกของคุณเอง คุณสามารถเปิดใช้งานลักษณะการทำงานนี้ได้เมื่อถูกสร้างขึ้นหรือเปิดใช้งานในภายหลังในวงจรการใช้งานแอปพลิเคชันของคุณ:
const { createLogger, Transports } = need('winston');// เปิดใช้งานการจัดการการปฏิเสธเมื่อคุณสร้าง logger.const logger = createLogger({ Transports: [ new Transports.File({ filename: 'combined.log' }) ] , rejectionHandlers: [ new Transports.File({ filename: 'rejections.log' }) ]});// หรือเปิดใช้งานในภายหลังโดยเพิ่มการขนส่งหรือใช้ `.rejections.handle`const logger = createLogger({ การขนส่ง: [ new Transports.File({ ชื่อไฟล์: 'combined.log' }) ]});// โทร rejections.handle ด้วยการขนส่งเพื่อจัดการ rejectionslogger.rejections.handle ( new Transports.File({ ชื่อไฟล์: '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 Jan 21 :00:00 - ข้อมูล: ระยะเวลาการทดสอบ = 1,000ms' // logger.profile('test');}, 1,000);
นอกจากนี้คุณยังสามารถเริ่มจับเวลาและเก็บข้อมูลอ้างอิงที่คุณสามารถโทร .done()
บน:
// ส่งคืนวัตถุที่สอดคล้องกับระยะเวลาที่กำหนด เมื่อเสร็จแล้ว // เรียกว่าตัวจับเวลาจะเสร็จสิ้นและบันทึกระยะเวลา เช่น: // constprofiler = logger.startTimer(); setTimeout (ฟังก์ชั่น () { profiler.done ({ ข้อความ: 'บันทึกข้อความ' }); }, 1,000);
ข้อความโปรไฟล์ทั้งหมดจะถูกตั้งค่าเป็นระดับ 'ข้อมูล' ตามค่าเริ่มต้น และทั้งข้อความและข้อมูลเมตาก็เป็นทางเลือก สำหรับข้อความโปรไฟล์แต่ละรายการ คุณสามารถแทนที่ระดับบันทึกเริ่มต้นได้โดยการจัดหาออบเจ็กต์ข้อมูลเมตาที่มีคุณสมบัติ level
:
logger.profile('test', { ระดับ: 'debug' });
winston
รองรับการสืบค้นบันทึกด้วยตัวเลือกที่เหมือน Loggly ดู API การค้นหา Loggly โดยเฉพาะ: File
, Couchdb
, Redis
, Loggly
, Nssocket
และ Http
const options = { จาก: วันที่ใหม่ () - (24 * 60 * 60 * 1,000) จนถึง: วันที่ใหม่ () จำกัด: 10 เริ่มต้น: 0 ลำดับ: 'desc' ฟิลด์: ['ข้อความ']} ;////// ค้นหารายการที่บันทึกไว้ระหว่างวันที่วันนี้ถึงเมื่อวาน//logger.query(options, function (err, results) { if (err) { /* TODO: handle me */ Throw err; } console.log(ผลลัพธ์);});
การสตรีมช่วยให้คุณสามารถสตรีมบันทึกของคุณกลับจากการขนส่งที่คุณเลือก
///// เริ่มต้นที่จุดสิ้นสุด//winston.stream({ start: -1 }).on('log', function(log) { console.log(log);});
ตัวบันทึกเริ่มต้นสามารถเข้าถึงได้ผ่านโมดูล winston
โดยตรง วิธีการใดๆ ที่คุณสามารถเรียกใช้บนอินสแตนซ์ของตัวบันทึกจะมีอยู่ในตัวบันทึกเริ่มต้น:
const winston = need('winston');winston.log('info', 'สวัสดีไฟล์บันทึกที่แจกจ่าย!');winston.info('สวัสดีบันทึกที่แจกจ่ายอีกครั้ง');winston.level = 'debug';winston.log ('debug', 'ตอนนี้ข้อความดีบั๊กของฉันถูกเขียนลงคอนโซลแล้ว!');
ตามค่าเริ่มต้น ไม่มีการตั้งค่าการขนส่งบนตัวบันทึกเริ่มต้น คุณต้องเพิ่มหรือลบการขนส่งผ่านทาง add()
และ remove()
วิธีการ:
ไฟล์ const = new winston.transports.File({ ชื่อไฟล์: 'combined.log' });const console = new winston.transports.Console();winston.add(console);winston.add(files);winston.remove (คอนโซล);
หรือทำได้ด้วยการเรียกเพียงครั้งเดียวเพื่อกำหนดค่า ():
winston.configure ({ การขนส่ง: [ ใหม่ winston.transports.File ({ ชื่อไฟล์: 'somefile.log' }) ]});
สำหรับเอกสารเพิ่มเติมเกี่ยวกับการทำงานกับการขนส่งแต่ละรายการที่ winston
สนับสนุน โปรดดูเอกสารของ winston
Transports
winston
บ่อยครั้งการรอให้บันทึกของคุณถูกเขียนก่อนที่จะออกจากกระบวนการมักจะเป็นประโยชน์ แต่ละอินสแตนซ์ของ winston.Logger
ยังเป็น [สตรีม Node.js] ด้วย เหตุการณ์ finish
จะเกิดขึ้นเมื่อบันทึกทั้งหมดถูกล้างไปยังการขนส่งทั้งหมดหลังจากการสตรีมสิ้นสุดลง
const Transport = new winston.transports.Console();const logger = winston.createLogger({ การขนส่ง: [ขนส่ง]});logger.on('finish', ฟังก์ชั่น (ข้อมูล) { // ข้อความบันทึก `ข้อมูล' ทั้งหมดมี ตอนนี้ถูกบันทึกแล้ว}); logger.info ('CHILL WINSTON!', { จริงจัง: จริง }); logger.end ();
นอกจากนี้ยังควรกล่าวถึงด้วยว่าตัวบันทึกยังปล่อยเหตุการณ์ 'ข้อผิดพลาด' หากมีข้อผิดพลาดเกิดขึ้นภายในตัวบันทึกซึ่งคุณควรจัดการหรือระงับหากคุณไม่ต้องการข้อยกเว้นที่ไม่สามารถจัดการได้:
///// จัดการกับข้อผิดพลาดที่เกิดขึ้นในตัวบันทึก //logger.on('error', function (err) { /* Do Something */ });
บ่อยครั้งในแอปพลิเคชันที่มีขนาดใหญ่กว่าและซับซ้อนกว่า จำเป็นต้องมีอินสแตนซ์ตัวบันทึกหลายตัวพร้อมการตั้งค่าที่แตกต่างกัน ตัวบันทึกแต่ละตัวมีหน้าที่รับผิดชอบในส่วนคุณลักษณะ (หรือหมวดหมู่) ที่แตกต่างกัน สิ่งนี้ถูกเปิดเผยใน winston
ในสองวิธี: ผ่าน winston.loggers
และอินสแตนซ์ของ winston.Container
ในความเป็นจริง winston.loggers
เป็นเพียงอินสแตนซ์ที่กำหนดไว้ล่วงหน้าของ winston.Container
:
const winston = need('winston');const { format } = winston;const { รวม, ป้ายกำกับ, json } = format;//// กำหนดค่าตัวบันทึกสำหรับ `category1`//winston.loggers.add('category1' , { รูปแบบ: รวม ( label ({ label: 'category one' }), json() ), การขนส่ง: [ new winston.transports.Console ({ ระดับ: 'silly' }), winston.transports.File ใหม่ ({ ชื่อไฟล์: 'somefile.log' }) ]});//// กำหนดค่าตัวบันทึกสำหรับ `category2`//winston.loggers.add('category2', { รูปแบบ: รวม ( ป้ายกำกับ ({ ป้ายกำกับ: 'หมวดหมู่ที่สอง' }), json() ), การขนส่ง: [ ใหม่ winston.transports.Http ({ โฮสต์: 'localhost', พอร์ต:8080 }) ]});
เมื่อติดตั้งตัวบันทึกของคุณแล้ว คุณสามารถกำหนดให้ winston ในไฟล์ใดก็ได้ในแอปพลิเคชันของคุณ และเข้าถึงตัวบันทึกที่กำหนดค่าไว้ล่วงหน้าเหล่านี้:
const winston = need('winston');//// หยิบตัวบันทึกที่กำหนดค่าไว้ล่วงหน้าของคุณ//const category1 = winston.loggers.get('category1');const category2 = winston.loggers.get('category2');category1. info('เข้าสู่ระบบการขนส่งไฟล์และคอนโซล');category2.info('เข้าสู่ระบบการขนส่ง http');
หากคุณต้องการจัดการ Container
ด้วยตัวเอง คุณสามารถสร้างอินสแตนซ์ได้:
const winston = need('winston');const { format } = winston;const { รวม, ป้ายกำกับ, json } = รูปแบบ; const container = new winston.Container();container.add('category1', { รูปแบบ: รวม ( label({ label: 'category one' }), json() ), การขนส่ง: [ new winston.transports.Console({ ระดับ: 'silly' }), ใหม่ winston.transports.File({ ชื่อไฟล์: 'somefile.log' }) ]});const category1 = 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 ({ ระดับ: 'ข้อมูล' การขนส่ง: [winston.transports.Console ใหม่ ({forceConsole: true })]});
npm ติดตั้งวินสตัน
เส้นด้ายเพิ่มวินสตัน
การทดสอบวินสตันทั้งหมดเขียนด้วย mocha
, nyc
และ assume
พวกเขาสามารถรันด้วย npm
การทดสอบเวลาต่อนาที