winston
نسخة؟ _winston@2
winston@3
node -v
_ v8.11.3
مع 3.xx:
const winston = require('winston')
const logger = winston.createLogger({
transports: [new winston.transports.Console()]
})
logger.info('test log', 'with a second parameter')
المخرجات:
{"level":"info","message":"test log"}
مع 2.xx:
const winston = require('winston')
const logger = new winston.Logger({
transports: [new winston.transports.Console()]
})
logger.info('test log', 'with a second parameter')
المخرجات:
info: test log with a second parameter
يجب إخراج:
{"level":"info","message":"test log with a second parameter"}
واجهت نفس المشكلة اليوم. أعتقد أنه خطأ نظرًا لأن وثائق الترقية تحتوي أيضًا على مثال كهذا هنا :
logger.info('transaction ok', { creditCard: 123456789012345 });
للتغلب على هذا حاليًا ، يمكنك إنشاء وظيفة تحلل المعطيات قبل تمريرها إلى winston
@ mulligan121 حسنًا ، لكني لا أريد استبدال كل بيان سجل في قاعدة الكود الخاصة بي ...
indexzero هل هذا تحت
الحل المؤقت:
const wrapper = ( original ) => {
return (...args) => original(args.join(" "));
};
winstonLogger.error = wrapper(winstonLogger.error);
winstonLogger.warn = wrapper(winstonLogger.warn);
winstonLogger.info = wrapper(winstonLogger.info);
winstonLogger.verbose = wrapper(winstonLogger.verbose);
winstonLogger.debug = wrapper(winstonLogger.debug);
winstonLogger.silly = wrapper(winstonLogger.silly);
هذا تغيير هائل بالنسبة لنا. إذا كان ذلك مقصودًا ، فيجب تفصيله في https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md
لذلك بعد المزيد من الاستقصاء ، وجدت أنك بحاجة إلى مُنسق splat من أجل طباعة وسيطات متعددة. اعتقدت أن هذا كان فقط لاستيفاء الوسيطة (أي الأشياء التي تحتوي على٪ s وما إلى ذلك) ، ولكن يبدو أنك تحتاجه فقط للقيام بـ logger.info("something", value)
.
لكن هذا لا يزال غريبًا بعض الشيء بالنسبة لي - أحصل على شيء يشبه JSON في الإخراج مع مفتاح "meta" ، على الرغم من أنني لا أستخدم تنسيق JSON:
logger.info('Test: %s', 1, 2, 3, 4);
ينتج عنه:
info: Test: 1 {"meta":[2,3,4]}
حتى المثال في الأمثلة لا ينتج ما يقول إنه سيفعله:
https://github.com/winstonjs/winston/blob/master/examples/interpolation.js#L20 -L21
info: test message first, second {"meta":{"number":123}}
لقد قمت بحلها باستخدام شيء من هذا القبيل:
const { version } = require('../package');
const { createLogger, format, transports } = require('winston');
const { combine, timestamp, colorize, label, printf, align } = format;
const { SPLAT } = require('triple-beam');
const { isObject } = require('lodash');
function formatObject(param) {
if (isObject(param)) {
return JSON.stringify(param);
}
return param;
}
// Ignore log messages if they have { private: true }
const all = format((info) => {
const splat = info[SPLAT] || [];
const message = formatObject(info.message);
const rest = splat.map(formatObject).join(' ');
info.message = `${message} ${rest}`;
return info;
});
const customLogger = createLogger({
format: combine(
all(),
label({ label: version }),
timestamp(),
colorize(),
align(),
printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${formatObject(info.message)}`)
),
transports: [new transports.Console()]
});
فيما يلي حل بديل شائع للسماح بمعلمات متعددة:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29
متعلق ب:
https://github.com/winstonjs/winston/issues/1377
هناك الكثير من الأشياء التي لا تعمل بالطريقة نفسها.
مرحبا ، أي تحديثات هنا؟ شكرا.
تنتظر أيضًا الطريقة الصحيحة لمحاكاة console.log(...args)
في winston ...
لقد أصلحنا عددًا من حالات الحافة / الزاوية حول splat
و meta
في 3.2.0
، لكن يبدو أن هذه لا تزال مشكلة (راجع: https://github.com / winstonjs / winston / pull / 1576 مقابل CHANGELOG.md
).
سوف نتأكد من التعامل مع هذا في 3.3.0
. شكرا يا رفاق صبركم.
كان هذا حلاً لي:
'use strict';
const { createLogger, format, transports } = require('winston');
const { SPLAT } = require('triple-beam');
const { combine, timestamp, label, printf, colorize } = format;
const formatObject = (param) => {
if (typeof param === 'string') {
return param;
}
if (param instanceof Error) {
return param.stack ? param.stack : JSON.stringify(param, null, 2);
}
return JSON.stringify(param, null, 2);
};
const logFormat = printf((info) => {
const { timestamp: ts, level, message } = info;
const rest = info[SPLAT] || [];
const msg = info.stack ? formatObject(info.stack) : formatObject(message);
let result = `${ts} ${level}: ${msg}`;
if (rest.length) {
result += `\n${rest.map(formatObject).join('\n')}`;
}
return result;
});
const logger = createLogger({
format: combine(
label({ label: 'app' }),
timestamp(),
logFormat,
),
transports: [
new transports.Console({
format: combine(colorize()),
handleExceptions: true,
}),
],
exceptionHandlers: [
new transports.File({ filename: 'exceptions.log' }),
],
});
عندما أحاول التسجيل بالحجج أحصل على إخراج غريب
var s = "Hello"
log.info("asdasda", s)
الحصول على الإخراج
{"0":"H","1":"e","2":"l","3":"l","4":"o","service":"XXXX","level":"info","message":"asdasda","timestamp":"2019-04-15 13:58:51"}
لقد استخدمت رمز البدء السريع العادي
شيء واحد لاحظته هو هذا:
آمل أن هذا يمكن / سيتم إصلاحه
ملاحظة: اختبرت هذا باستخدام أحدث إصدار تم إصداره من Winston ، ويبدو أن نظرة سريعة على الكود تشير إلى أنه لا يزال على هذا النحو (الذي يحتوي على إصلاحات أخرى على ما يبدو)
بعض التحسينات على حلluislobo الصورة 👏
%s %d or %j
لرسائل مثل logger.info(`hello %s`,'world')
printf
trimEnd
إذا لم يتم توفير وسيطات الإضافة في Loogerconst { version } = require('../package');
const { createLogger, format, transports } = require('winston');
const { combine, timestamp, colorize, label, printf, align } = format;
const { SPLAT } = require('triple-beam');
const { isObject,trimEnd } = require('lodash');
function formatObject(param) {
if (isObject(param)) {
return JSON.stringify(param);
}
return param;
}
const all = format((info) => {
const splat = info[SPLAT] || []
const isSplatTypeMessage =
typeof info.message === 'string' &&
(info.message.includes('%s') || info.message.includes('%d') || info.message.includes('%j'))
if (isSplatTypeMessage) {
return info
}
const message = formatObject(info.message)
const rest = splat
.map(formatObject)
.join(' ')
info.message = trimEnd(`${message} ${rest}`)
return info
});
const customLogger = createLogger({
format: combine(
colorize(),
all(),
label({ label: version }),
timestamp(),
align(),
printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`)
),
transports: [new transports.Console()]
});
هل هناك أي تحديث آخر لهذا قد يكون في عداد المفقودين؟ يبدو أن هناك دعمًا قويًا لإعادة إضافة هذه الميزة ، لكن الالتزام الأخير بهذا كان منذ ما يقرب من 6 أشهر.
مرحبًا ، هناك مصد ضخم وسدادة عرض ، تحاول الانتقال إلى 3.X ، وربما ستحتفظ بـ 2.x لفترة من الوقت.
قليلا بخيبة أمل :(
هذا ما نجح معي:
const { format, createLogger, transports } = require('winston');
const jsonStringify = require('fast-safe-stringify');
const logLikeFormat = {
transform(info) {
const { timestamp, label, message } = info;
const level = info[Symbol.for('level')];
const args = info[Symbol.for('splat')];
const strArgs = args.map(jsonStringify).join(' ');
info[Symbol.for('message')] = `${timestamp} [${label}] ${level}: ${message} ${strArgs}`;
return info;
}
};
const debugFormat = {
transform(info) {
console.log(info);
return info;
}
};
const logger = createLogger({
format: format.combine(
// debugFormat, // uncomment to see the internal log structure
format.timestamp(),
format.label({ label: 'myLabel' }),
logLikeFormat,
// debugFormat, // uncomment to see the internal log structure
),
transports: [
new transports.Console()
]
});
logger.info('foo', 'bar', 1, [2, 3], true, { name: 'John' });
والذي ينتج عنه: 2019-07-04T21:30:08.455Z [myLabel] info: foo "bar" 1 [2,3] true {"name":"John"}
يعين format.combine
أساسًا خط أنابيب لكائن info
. لكل دالة تنسيق ، يتم استدعاء transform
ويجب كتابة رسالة السجل النهائية على info[Symbol.for('message')]
أتمنى أن يساعدك هذا
أردت حلاً يدعم %d
، %o
إلخ ، ولكن لا يزال يتم تضمين أي وسيطات بشكل افتراضي ، بحيث يتم عرض logger.info('hello %d %j', 42, {a:3}, 'some', 'more', 'arguments')
النحو التالي:
hello 42 {"a": 3} some more arguments
انتهى الحل باستخدام الرمز splat
ولكن استدعى يدويًا util.format()
مباشرة من printf
، والذي يتضمن افتراضيًا أي وسيطات راحة:
const {format} = require('util');
const winston = require('winston');
const {combine, timestamp, printf} = winston.format;
const SPLAT = Symbol.for('splat');
const transport = new winston.transports.Console({
format: combine(
timestamp(),
printf(({timestamp, level, message, [SPLAT]: args = []}) =>
`${timestamp} - ${level}: ${format(message, ...args)}`)
)
})
إذا كنت لا تريد printf
يمكنك بالطبع إضافة تحويل يقوم ببساطة بتوسيع args إلى info.message
، ثم تنسيق النتيجة النهائية بالطريقة التي تريدها:
format: combine(
{
transform(info) {
const {[SPLAT]: args = [], message} = info;
info.message = format(message, ...args);
return info;
}
},
simple()
)
تكمن مشكلة استخدام format.splat()
أنه يستهلك وسيطات المطابقة ولكن يبدو أنه يتخلص من الباقي. من خلال استدعاء util.format()
بنفسي ، يمكنني تجاوز هذا السلوك.
نفس المشكلة ، أي تحديث بخصوص هذا واحد؟ أنا أحب وينستون ، لكن هذا يصيبني بالجنون عندما لا أستطيع طباعة جميع الوسائط التي تم تمريرها إلى المسجل ، وهو ما يمكنني فعله باستخدام console.log()
.
@ fr1sk هل جربت التنسيق أعلاه؟ إنه يعطي console.log()
مثل السلوك (تنفيذ العقدة console.log()
يستخدم داخليًا util.format()
afaik).
إنه لأمر مخيب للآمال أن هذه المشكلة لم يتم حلها بعد ، وأن مشكلتي ذات الصلة قد تم إغلاقها.
أنا أعمل مع العديد من الفرق المختلفة وهم جميعًا يشاركونني الإحباط الناتج عن فقدان DX السابق عند الانتقال إلى الإصدار 3.
لقد أمضيت يومًا كاملاً في تجربة الأشياء.
كانت الحلول المذكورة أعلاه قريبة ولكني كنت أفتقد التلوين وكسر الأسطر للحجج الإضافية.
IMO ، يجب أن يكون تسجيل الدخول إلى وحدة التحكم أمرًا ممتعًا.
ها هي محاولتي لتحقيق ذلك ...
const winston = require('winston');
const chalk = require('chalk');
const logger = new winston.Logger({
transports: [
new winston.transports.Console({
level: 'info',
colorize: true,
prettyPrint: true,
timestamp: true
})
]
});
logger.info({ one: 1, two: 2, three: 3 });
logger.info(chalk.blue('[TEST]:'), { one: 1, two: 2, three: 3 }, [4, 5, 6]);
logger.info(chalk.blue('[TEST]:'), null, undefined, 'one', 2, { 3: 3, 4: '4' });
logger.info(chalk.blue('[TEST]:'), chalk.yellow('Bombastic'), () => {}, /foo/);
logger.error(chalk.blue('[ERR]:'), new Error('Error number 1'));
logger.error(new Error('Error number 2'));
const { createLogger, format, transports } = require('winston');
const { inspect } = require('util');
const chalk = require('chalk');
const hasAnsi = require('has-ansi');
function isPrimitive(val) {
return val === null || (typeof val !== 'object' && typeof val !== 'function');
}
function formatWithInspect(val) {
const prefix = isPrimitive(val) ? '' : '\n';
const shouldFormat = typeof val !== 'string' || !hasAnsi(val);
return prefix + (shouldFormat ? inspect(val, { depth: null, colors: true }) : val);
}
const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.errors({ stack: true }),
format.colorize(),
format.printf(info => {
const msg = formatWithInspect(info.message);
const splatArgs = info[Symbol.for('splat')] || [];
const rest = splatArgs.map(data => formatWithInspect(data)).join(' ');
return `${info.timestamp} - ${info.level}: ${msg} ${rest}`;
})
),
transports: [new transports.Console()]
});
logger.info({ one: 1, two: 2, three: 3 });
logger.info(chalk.blue('[TEST]:'), { one: 1, two: 2, three: 3 }, [4, 5, 6]);
logger.info(chalk.blue('[TEST]:'), null, undefined, 'one', 2, { 3: 3, 4: '4' });
logger.info(chalk.blue('[TEST]:'), chalk.yellow('Bombastic'), () => {}, /foo/);
logger.error(chalk.blue('[ERR]:'), new Error('Error number 1'));
logger.error(new Error('Error number 2'));
chalk
info.message
مجرد سلسلة وأن مسار المكدس موجود في خاصية stack
message
كالوسيطة الأولى يطبع message
، مع تجاهل أي خصائص أخرىinfo.message
(وهي عادةً قيمة الوسيطة الأولى) ، مما يؤدي إلى رؤية رسالة الخطأ مرتينلم يساعد اللعب مع منسق errors
.
يمكننا التعامل مع أخطاء التنسيق ولكنها اختراق:
function formatWithInspect(val) {
+ if (val instanceof Error) {
+ return '';
+ }
const prefix = isPrimitive(val) ? '' : '\n';
const shouldFormat = typeof val !== 'string' || !hasAnsi(val);
return prefix + (shouldFormat ? inspect(val, { depth: null, colors: true }) : val);
}
...
format.printf((info) => {
const msg = formatWithInspect(info.message);
const splatArgs = info[Symbol.for('splat')] || [];
const rest = splatArgs.map((data) => formatWithInspect(data)).join(' ');
+ const stackTrace = info.stack ? `\n${info.stack}` : '';
return `${info.timestamp} - ${info.level}: ${msg} ${rest}${stackTrace}`;
})
...
إنه يعمل معي باستخدام info[Symbol.for('splat')]
const logger = winston.createLogger({
level: 'debug',
transports: [
...
],
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf((info: any) => {
const timestamp = info.timestamp.trim();
const level = info.level;
const message = (info.message || '').trim();
const args = info[Symbol.for('splat')];
const strArgs = (args || []).map((arg: any) => {
return util.inspect(arg, {
colors: true
});
}).join(' ');
return `[${timestamp}] ${level} ${message} ${strArgs}`;
})
)
});
أنا أفهم أن الإصدارات الرئيسية تقدم تغييرات جذرية ، لكن يا إلهي ...
لم يمنحني أي من الحلول نفس سلوك winston v2.
الحلول من henhal و yamadashy لها نفس المشكلة: يتم عرض قيمة الرسالة كسلسلة.
إنشاء رسالة سجل logger.debug(err)
:
debug: Error: ETIMEDOUT
بينما logger.debug('anystringhere', err)
ينشئ:
debug: anystringhereError: ETIMEDOUT { RequestError: Error: ETIMEDOUT
at new RequestError (/path/to/node_modules/request-promise-core/lib/errors.js:14:15)
<the rest of full error stack here>
المسألة الثانية هي أن الحجج الإضافية يتم قمعها عند الاستخدام مع مستوى المعلومات - يبدو أن Winston v3 يتعامل مع هذه الطريقة الأخرى قبل التنسيق.
المشكلة الثالثة هي الفراغ المفقود بين رسالتين (لاحظ "anystringhereError").
تكوين مسجل v3 الحالي الخاص بي:
const { format } = require('util');
const winston = require("winston");
const logger = winston.createLogger({
transports: [
new winston.transports.Console({
level: 'debug'
format: winston.format.combine(
winston.format.colorize(),
winston.format.align(),
winston.format.printf(
({level, message, [Symbol.for('splat')]: args = []}) => `${level}: ${format(message, ...args)}`
)
)
}),
]
});
module.exports = logger;
كان لدي ما يكفي من ذلك وسأعود إلى Winston v2 مع هذا فقط:
const Winston = require("winston");
const logger = new Winston.Logger({
transports: [
new Winston.transports.Console({
level: 'debug',
handleExceptions: true,
json: false,
colorize: true,
})
],
});
module.exports = logger;
لا يحتوي هذا التكوين v2 على المشكلات المذكورة أعلاه.
أرغب في مشاركة إعداد Winston الخاص بي:
const util = require('util');
const { createLogger, format, transports } = require('winston');
const { combine, colorize, timestamp, printf, padLevels} = format;
const myFormat = printf(({ level, message, label, timestamp, ...rest }) => {
const splat = rest[Symbol.for('splat')];
const strArgs = splat ? splat.map((s) => util.formatWithOptions({ colors: true, depth: 10 }, s)).join(' ') : '';
return `${timestamp} ${level} ${util.formatWithOptions({ colors: true, depth: 10}, message)} ${strArgs}`;
});
const logger = createLogger({
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
format: combine(
colorize(),
timestamp({
format: 'YYYY-M-DD HH:mm:ss',
}),
padLevels(),
myFormat
),
transports: [new transports.Console()],
});
logger.info('test info');
logger.error('test error');
logger.debug('test debug');
فيما يلي حل بديل شائع للسماح بمعلمات متعددة:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29
هنا رابط محدث للحل المقترح
https://github.com/rooseveltframework/roosevelt/blob/0.13.0/lib/tools/logger.js
المنجم هو نوع من الاقتراحات العظيمة alexilyaev :
const { omit } = require('lodash');
const hasAnsi = require('has-ansi');
function isPrimitive(val) {
return val === null || (typeof val !== 'object' && typeof val !== 'function');
}
function formatWithInspect(val) {
if (val instanceof Error) {
return '';
}
const shouldFormat = typeof val !== 'string' && !hasAnsi(val);
const formattedVal = shouldFormat
? inspect(val, { depth: null, colors: true })
: val;
return isPrimitive(val) ? formattedVal : `\n${formattedVal}`;
}
// Handles all the different log formats for console
function getDomainWinstonLoggerFormat(format) {
return format.combine(
format.timestamp(),
format.errors({ stack: true }),
format.colorize(),
format.printf((info) => {
const stackTrace = info.stack ? `\n${info.stack}` : '';
// handle single object
if (!info.message) {
const obj = omit(info, ['level', 'timestamp', Symbol.for('level')]);
return `${info.timestamp} - ${info.level}: ${formatWithInspect(obj)}${stackTrace}`;
}
const splatArgs = info[Symbol.for('splat')] || [];
const rest = splatArgs.map(data => formatWithInspect(data)).join('');
const msg = formatWithInspect(info.message);
return `${info.timestamp} - ${info.level}: ${msg}${rest}${stackTrace}`;
}),
);
}
لسجلات مثل:
logger.info({
joe: 'blow',
});
logger.info('Single String');
logger.info('With Func ', () => {}, /foo/);
logger.info('String One ', 'String Two');
logger.info('String One ', 'String Two ', 'String Three');
logger.info('Single Object ', {
test: 123,
});
logger.info(
'Multiple Objects ',
{
test: 123,
},
{
martin: 5555,
},
);
logger.error('Error: ', new Error('Boom!'));
ينتج مثل هذا - وهو أمر جيد لجميع السيناريوهات الخاصة بي:
مرحبًا ، أنا أبدأ بـ Winston ، لم أستخدم الإصدار 2 مطلقًا ، لذا فأنا على الإصدار 3.2.1
كنت أحاول ببساطة أن أفعل:
import winston, { format } from 'winston';
winston.format(format.combine(format.splat(), format.simple()));
winston.info('buildFastify dataPath %s', opts.dataPath);
وتأمل أن يعمل الاستيفاء الخيطي ؛ لكن كلا.
{"level":"info","message":"buildFastify dataPath %s"}
عندما كنت أتوقع
{"level":"info","message":"buildFastify dataPath /My/Data/Path"}
هذه القضية هي نفس الشيء بطريقة أو بأخرى؟ أم أنني مجبر على استخدام الدالة logger.log('info', .....)
بدلاً من ذلك؟
الحدث الذي يحاول هذا لا يعمل.
winston.log('info', 'buildFastify dataPath %s', opts.dataPath);
انتاج:
{"level":"info","message":"buildFastify dataPath %s"}
شكرا لمن نشر الاقتراحات أعلاه.
اللعنة ، لقد رميت يومًا ما فقط لدمج Winston 3 في مشروعي: /
لقد أصابني هذا اليوم - أدركت أن أداة التسجيل الجديدة الرائعة الخاصة بي كانت ترمي جميع حججتي ...rest
. قد لا يعمل هذا مع الجميع أو كل حالة استخدام ، ولكن في حالتي وجدت أنه من المقبول فقط تغليف كل ما أريد تسجيله كمصفوفة. إنها ليست الأجمل ، لكنها أخف من بعض الحلول [الذكية جدًا] التي تتطلب المزيد من التعليمات البرمجية. آمل أن يساعد هذا شخص آخر!
logger.info(["Something happened!", foo, bar]);
مزعج حقًا أنهم قرروا إجراء تغيير كبير بهذا الحجم وما زالوا لم
بغض النظر عن رغبتي في مشاركة الحل الذي وجدته مضغوطًا تمامًا ويتبع كيفية تنفيذ node js لـ console.log باستخدام util.format
const winstonLogger= createLogger(...);
const writeLogType = (logLevel) => {
return function () {
const args = Array.from(arguments);
winstonLogger[logLevel](util.format(...args));
};
};
const logger = {
silly: writeLogType('silly'),
debug: writeLogType('debug'),
verbose: writeLogType('verbose'),
info: writeLogType('info'),
warn: writeLogType('warn'),
error: writeLogType('error'),
};
أرغب في الاتصال وطلب إضافة هذه الميزة إلى جوهر Winston. حاليًا ، أنا أستخدم المنسق المخصص بـ splat
لتحقيق هذه الوظيفة ، والتي تبدو بصراحة شديدة الاختراق. سيكون من الجيد أن يكون لديك وظائف تتطابق مع console.log
أي تحديثات؟
إلى جانب السلوكيات المذكورة أعلاه لـ v3 ، أود إضافة هذا أيضًا:
logger.info('param 1', { propInJson1: 'propInJson 1', propInJson2: 'propInJson 2' });
سينتج هذا
{"propInJson1":"propInJson 1","propInJson2":"propInJson 2","level":"info","message":"param 1"}
الإصدار الذي أستخدمه: (v3.2.1)
التكوينات:
winstonLogger.add(new winston.transports.Console());
ما زلت لا أفهم كيفية إخراج قيم متعددة في Winston.
أردت فقط استبدال console.log('Hello', var1, '!')
بـ logger.log('Hello', var1, '!')
.
بصراحة ، تؤدي محاولة استخدام Winston دائمًا إلى إهدار الكثير من الوقت ومشاكل مفاجئة في التسجيل.
مزعج حقًا أنهم قرروا إجراء تغيير كبير بهذا الحجم وما زالوا لم
بغض النظر عن رغبتي في مشاركة الحل الذي وجدته مضغوطًا تمامًا ويتبع كيفية تنفيذ node js لـ console.log باستخدام
util.format
const winstonLogger= createLogger(...); const writeLogType = (logLevel) => { return function () { const args = Array.from(arguments); winstonLogger[logLevel](util.format(...args)); }; }; const logger = { silly: writeLogType('silly'), debug: writeLogType('debug'), verbose: writeLogType('verbose'), info: writeLogType('info'), warn: writeLogType('warn'), error: writeLogType('error'), };
أيضًا ، استخدم util.formatWithOptions({ colors: true }, ...args);
للحصول على مخرجات طباعة ملونة كما هو الحال مع console.log
العادي
هذا يعمل بالنسبة لي. combineMessageAndSplat
يجمع بين الرسالة و splat باستخدام صيغة util.format
const winston = require("winston");
const util = require('util');
const combineMessageAndSplat = () => {
return {transform: (info, opts) => {
//combine message and args if any
info.message = util.format(info.message, ...info[Symbol.for('splat')] || [] )
return info;
}
}
}
const logger = winston.createLogger({
format:
winston.format.combine(
combineMessageAndSplat(),
winston.format.simple()
)
});
logger.add(new winston.transports.Console({
level: 'info'
})
);
logger.info("string"); // info: string
logger.info({a:1,b:[{c:[1]}]}); // info: { a: 1, b: [ { c: [Array] } ] }
logger.info("1","2",{a:1}); // info: 1 2 { a: 1 }
logger.info([{},""]); // info: [ {}, '' ]
logger.error(new Error()); // error: Error ... at Object.<anonymous>
كان علي أن أتوافق مع أساليب وحدة التحكم * ، والتوجيه على كل ما سبق ، و ...
لكن: يجب أن يُظهر إخراج الملف تفاصيل الكائن.
لذلك انتهى بي الأمر بـ:
// make File and FileList parseable // from: https://stackoverflow.com/a/51939522/1644202
File.prototype.toObject = function () {
return Object({
name: String(this.name),
path: String(this.path),
lastModified: parseInt(this.lastModified),
lastModifiedDate: String(this.lastModifiedDate),
size: parseInt(this.size),
type: String(this.type)
});
};
FileList.prototype.toArray = function () {
return Array.from(this).map(function (file) {
return file.toObject()
});
};
// this fixes: winston console transport to use the original console functions and all the colorization/folding/etc that comes with it
const Transport = require('winston-transport');
class WebDeveloperConsole extends Transport {
constructor(opts) {
super(opts);
}
log(info, callback) {
(window.console[info.level] || window.console.log).apply(window.console, [info.timestamp, ...info.message]);
callback();
}
};
// Electron app console output
class AppConsole extends Transport {
constructor(opts) {
super(opts);
const { remote } = require('electron');
this.electronConsole = remote.getGlobal('console');
}
log(info, callback) {
(this.electronConsole[info.level] || this.electronConsole.log).apply(this.electronConsole, [info.timestamp, ...info.message]);
callback();
}
};
const util = require('util');
const {
createLogger,
transports,
format
} = require('winston');
let logger = createLogger({
level: 'trace',
levels: {
error: 0,
warn: 1,
info: 2,
//http: 3, no console.* methods
//verbose: 4,
debug: 3,
trace: 4
},
format: format.combine(
format.prettyPrint(),
format.timestamp({
format: 'DD-MM-YYYY hh:mm:ss A'
}),
{
transform(info) {
const { timestamp, message } = info;
const level = info[Symbol.for('level')];
const args = [message, ...(info[Symbol.for('splat')] || [])]; // join the args back into one arr
info.message = args; // for all custom transports (mainly the console ones)
let msg = args.map(e => {
if (e.toString() == '[object FileList]')
return util.inspect(e.toArray(), true, 10);
else if (e.toString() == '[object File]')
return util.inspect(e.toObject(), true, 10);
else if (e.toString() == '[object Object]') {
return util.inspect(e, true, 5);
}
else if (e instanceof Error)
return e.stack
else
return e;
}).join(' ');
info[Symbol.for('message')] = `${timestamp} - ${level}: ${msg}`; // for inbuild transport / file-transport
return info;
}
},
),
transports: [
//new transports.Console(),
new WebDeveloperConsole(),
new AppConsole(),
...
],
...
});
indexzero هل كنت تتساءل عما إذا كنت لا تزال تخطط لمعالجة هذا الأمر في وقت ما؟
أنا أستكشف winston لاستخدامه في مشروعي ، وأتساءل الآن هل يستحق المخاطرة لأن هذه المشكلة مفتوحة لأكثر من عامين. بالنسبة لي ، تبدو هذه وظيفة أساسية لأي إطار عمل للتسجيل
التعليق الأكثر فائدة
هذا تغيير هائل بالنسبة لنا. إذا كان ذلك مقصودًا ، فيجب تفصيله في https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md