winston
Version?_winston@2
winston@3
node -v
Ausgaben:_ v8.11.3
Mit 3.xx:
const winston = require('winston')
const logger = winston.createLogger({
transports: [new winston.transports.Console()]
})
logger.info('test log', 'with a second parameter')
Ausgänge:
{"level":"info","message":"test log"}
Mit 2.xx:
const winston = require('winston')
const logger = new winston.Logger({
transports: [new winston.transports.Console()]
})
logger.info('test log', 'with a second parameter')
Ausgänge:
info: test log with a second parameter
Es sollte ausgegeben werden:
{"level":"info","message":"test log with a second parameter"}
Ich bin heute auf das gleiche Problem gestoßen. Ich glaube, es ist ein Fehler, da die Upgrade-Dokumentation auch ein Beispiel wie dieses hier enthält :
logger.info('transaction ok', { creditCard: 123456789012345 });
Um dies zu umgehen, können Sie derzeit eine Funktion erstellen, die die Argumente analysiert, bevor sie an winston übergeben wird
@mulligan121 Okay, aber ich möchte nicht jede Log-Anweisung in meiner Codebasis ersetzen ...
@indexzero Ist das unter Ihrem Radar? Ich denke, dies ist eine große bahnbrechende Änderung. Es verhindert tatsächlich den Wechsel von 2.x auf 3.x, da wir jeden Log-Eintrag ändern müssen
Temporäre Problemumgehung:
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);
Für uns ist dies eine RIESIGE bahnbrechende Veränderung. Wenn es beabsichtigt ist, sollte es in https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md beschrieben werden
Nach einigen weiteren Untersuchungen habe ich also festgestellt, dass Sie den Splat-Formatierer benötigen, damit mehrere Argumente gedruckt werden können. Ich dachte, das wäre nur für die Argumentinterpolation (dh Sachen mit %s usw.), aber es scheint, dass Sie es nur brauchen, um logger.info("something", value)
zu tun.
Aber das ist immer noch ein bisschen seltsam für mich - ich bekomme etwas, das wie JSON in der Ausgabe mit einem Schlüssel "meta" aussieht, obwohl ich kein JSON-Format verwende:
logger.info('Test: %s', 1, 2, 3, 4);
Produziert:
info: Test: 1 {"meta":[2,3,4]}
Selbst das Beispiel in den Beispielen liefert nicht das, was es verspricht:
https://github.com/winstonjs/winston/blob/master/examples/interpolation.js#L20 -L21
info: test message first, second {"meta":{"number":123}}
Ich habe es mit etwas in dieser Richtung gelöst:
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()]
});
Hier ist eine gängige Problemumgehung, um mehrere Parameter zuzulassen:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29
Bezüglich:
https://github.com/winstonjs/winston/issues/1377
Es gibt einfach zu viele Dinge, die nicht gleich funktionieren.
Hallo, gibt es hier Updates? Danke.
Wartet auch auf die richtige Methode, um console.log(...args)
in Winston zu emulieren ...
Wir haben eine Reihe der Kanten-/Eckfälle um splat
und meta
in 3.2.0
behoben, aber es scheint, dass dies immer noch ein Problem ist (siehe: https://github.com /winstonjs/winston/pull/1576 für CHANGELOG.md
).
Stellt sicher, dass dies in 3.3.0
gehandhabt wird. Danke für eure Geduld Leute.
Dies war ein Workaround für mich:
'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' }),
],
});
Wenn ich versuche, mich mit Argumenten anzumelden, bekomme ich eine seltsame Ausgabe
var s = "Hello"
log.info("asdasda", s)
Ausgabe erhalten
{"0":"H","1":"e","2":"l","3":"l","4":"o","service":"XXXX","level":"info","message":"asdasda","timestamp":"2019-04-15 13:58:51"}
Ich habe den normalen Schnellstartcode verwendet
Eine Sache die mir aufgefallen ist ist folgendes:
Hoffe das kann/wird behoben
Hinweis: Getestet mit der neuesten veröffentlichten Version von Winston, ein kurzer Blick auf den Code scheint darauf hinzudeuten, dass es in Master immer noch so ist (was anscheinend andere Fixes enthält).
Einige Verbesserungen gegenüber @luislobo ‚s Lösung 👏
%s %d or %j
für Nachrichten wie logger.info(`hello %s`,'world')
printf
trimEnd
wenn zusätzliche Argumente im Logger nicht bereitgestellt werdenconst { 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()]
});
Irgendwelche weiteren Updates dazu, die ich möglicherweise vermisse? Es scheint, als ob es ziemlich starke Unterstützung dafür gibt, dass diese Funktion erneut hinzugefügt wird, aber die letzte Zusage dazu liegt fast 6 Monate zurück.
Hallo zusammen, riesiger Bumper und Showstopper, der versucht, auf die 3.X zu migrieren, wird die 2.x wahrscheinlich eine Weile behalten.
Ein bisschen enttäuscht :(
Das hat bei mir funktioniert:
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' });
was ergibt: 2019-07-04T21:30:08.455Z [myLabel] info: foo "bar" 1 [2,3] true {"name":"John"}
Grundsätzlich legt format.combine
eine Pipeline für ein info
Objekt fest. Für jede Formatfunktion wird transform
aufgerufen und die letzte Protokollnachricht sollte in info[Symbol.for('message')]
hoffe das hilft
Ich wollte eine Lösung, die %d
, %o
usw. unterstützt, aber standardmäßig immer noch alle Restargumente enthält, sodass logger.info('hello %d %j', 42, {a:3}, 'some', 'more', 'arguments')
wie folgt gerendert wird:
hello 42 {"a": 3} some more arguments
Meine Lösung dafür endete mit dem splat
Symbol, aber dem manuellen Aufrufen von util.format()
direkt aus printf
, das standardmäßig alle Restargumente enthält:
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)}`)
)
})
Wenn Sie printf
nicht möchten, können Sie natürlich stattdessen eine Transformation hinzufügen, die die Argumente einfach in info.message
, und dann das Endergebnis nach Ihren Wünschen formatieren:
format: combine(
{
transform(info) {
const {[SPLAT]: args = [], message} = info;
info.message = format(message, ...args);
return info;
}
},
simple()
)
Das Problem bei der Verwendung von format.splat()
besteht darin, dass es die passenden Argumente verbraucht, aber den Rest scheinbar wegwirft. Indem ich util.format()
selbst aufrufe, kann ich dieses Verhalten überschreiben.
Gleiches Problem, gibt es diesbezüglich ein Update? Ich liebe Winston, aber es macht mich verrückt, wenn ich nicht alle an den Logger übergebenen Argumente ausgeben kann, was ich mit console.log()
tun kann.
@fr1sk Hast du meine obige Formatierung ausprobiert? Es ergibt ein console.log()
ähnliches Verhalten (die console.log()
Implementierung des Knotens verwendet intern util.format()
afaik).
Es ist enttäuschend, dass dieses Problem immer noch nicht behoben wurde und mein damit verbundenes Problem behoben wurde.
Ich arbeite mit vielen verschiedenen Teams zusammen und alle teilen die Frustration, dass ich bei der Migration auf v3 frühere DX verloren habe.
Ich habe einen ganzen Tag damit verbracht, Dinge auszuprobieren.
Die obigen Lösungen waren nah dran, aber mir fehlten die Einfärbung und der Zeilenumbruch von zusätzlichen Argumenten.
IMO, die Anmeldung an der Konsole sollte angenehm sein.
Hier ist mein Versuch, es zu verwirklichen...
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
nur eine Zeichenfolge ist und sich der Stapeltrakt in der Eigenschaft stack
message
Eigenschaft als erstes Argument gibt nur message
, alle anderen Eigenschaften werden verworfeninfo.message
(was normalerweise der Wert des ersten Arguments ist), was dazu führt, dass die Fehlermeldung zweimal angezeigt wirdHerumspielen mit dem errors
Formatierer hat nicht geholfen.
Wir können mit den Fehlern bei der Formatierung umgehen, aber es ist hackig:
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}`;
})
...
bei mir funktioniert es mit 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}`;
})
)
});
Ich verstehe, dass Hauptversionen grundlegende Änderungen einführen, aber meine Güte...
Keine der Lösungen gab mir das gleiche Verhalten wie winston v2.
Lösungen von @henhal und @yamadashy haben beide das gleiche Problem: Der Nachrichtenwert wird als String
logger.debug(err)
Protokollnachricht erstellen:
debug: Error: ETIMEDOUT
während logger.debug('anystringhere', err)
erstellt:
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>
Das zweite Problem ist, dass die zusätzlichen Argumente bei der Verwendung mit info level unterdrückt werden - Winston v3 scheint dies vor der Formatierung anders zu handhaben.
Drittes Problem ist das fehlende Leerzeichen zwischen 2 Nachrichten (beachte "anystringhereError").
Meine aktuelle v3-Logger-Konfiguration:
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;
Ich hatte genug davon und werde nur mit diesem zurück zu Winston v2 wechseln:
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;
Diese v2-Konfiguration weist die oben genannten Probleme nicht auf.
Ich möchte mein Winston-Setup teilen:
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');
Hier ist eine gängige Problemumgehung, um mehrere Parameter zuzulassen:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29
hier ist der aktualisierte Link zur vorgeschlagenen Lösung
https://github.com/rooseveltframework/roosevelt/blob/0.13.0/lib/tools/logger.js
Meins ist eine Variation von @alexilyaev großartigen Vorschlägen:
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}`;
}),
);
}
für Protokolle wie:
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!'));
Es wird so ausgegeben - was für alle meine Szenarien gut ist:
Hey, ich fange mit Winston an, habe noch nie v2 verwendet, also bin ich auf v3.2.1
Ich habe versucht, einfach zu tun:
import winston, { format } from 'winston';
winston.format(format.combine(format.splat(), format.simple()));
winston.info('buildFastify dataPath %s', opts.dataPath);
Und hoffen, dass die String-Interpolation funktioniert; aber nein.
{"level":"info","message":"buildFastify dataPath %s"}
Als ich erwartet hatte
{"level":"info","message":"buildFastify dataPath /My/Data/Path"}
Dieses Problem ist irgendwie dasselbe? Oder bin ich gezwungen, stattdessen die Funktion logger.log('info', .....)
verwenden?
Event versucht, dies zu versuchen, funktioniert nicht.
winston.log('info', 'buildFastify dataPath %s', opts.dataPath);
Ausgang:
{"level":"info","message":"buildFastify dataPath %s"}
Danke an die, die die obigen Vorschläge gepostet haben.
Verdammt, ich habe es eines Tages weggeworfen, nur um Winston 3 in mein Projekt zu integrieren :/
Dieser hat mich heute getroffen - mir wurde klar, dass mein schicker neuer Logger alle meine ...rest
Argumente warf. Dies funktioniert möglicherweise nicht für jeden oder jeden Anwendungsfall, aber in meinem Fall fand ich es akzeptabel, einfach alles, was ich wollte, als Array zu protokollieren. Es ist nicht das schönste, aber es ist leichter als einige der [sehr cleveren] Workarounds, die mehr Code erfordern. Hoffe das hilft jemand anderem!
logger.info(["Something happened!", foo, bar]);
Wirklich ärgerlich, dass sie sich entschieden haben, eine so große Änderung vorzunehmen und sie NOCH NICHT im Migrationshandbuch oder in der Dokumentation erwähnt haben.
Unabhängig davon wollte ich meine Lösung teilen, die ich ziemlich kompakt fand und folgte, wie node js console.log mit util.format
implementiert
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'),
};
Ich möchte mich einmischen und bitten, dass diese Funktion zum Kern von Winston hinzugefügt wird. Derzeit verwende ich den benutzerdefinierten Formatierer mit splat
, um diese Funktionalität zu erreichen, die sich ehrlich gesagt sehr hackig anfühlt. Es wäre schön, Funktionen zu haben, die console.log
Irgendwelche Updates?
Neben den oben genannten Verhaltensweisen für v3 möchte ich auch Folgendes hinzufügen:
logger.info('param 1', { propInJson1: 'propInJson 1', propInJson2: 'propInJson 2' });
wird das produzieren
{"propInJson1":"propInJson 1","propInJson2":"propInJson 2","level":"info","message":"param 1"}
die von mir verwendete Version: (v3.2.1)
Die Konfigurationen:
winstonLogger.add(new winston.transports.Console());
Ich verstehe immer noch nicht, wie man mehrere Werte in Winston ausgibt.
Ich wollte nur console.log('Hello', var1, '!')
durch logger.log('Hello', var1, '!')
ersetzen.
Um ehrlich zu sein, führt der Versuch, Winston zu verwenden, immer zu viel Zeitverschwendung und überraschenden Problemen bei der Protokollierung.
Wirklich ärgerlich, dass sie sich entschieden haben, eine so große Änderung vorzunehmen und sie NOCH NICHT im Migrationshandbuch oder in der Dokumentation erwähnt haben.
Unabhängig davon wollte ich meine Lösung teilen, die ich ziemlich kompakt fand und folgte, wie node js console.log mit
util.format
implementiertconst 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'), };
Verwenden Sie außerdem util.formatWithOptions({ colors: true }, ...args);
, um eine farbige Druckausgabe wie bei normalen console.log
Das funktioniert bei mir. combineMessageAndSplat
kombiniert Nachricht und Splat mit 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>
Ich musste mich an die console.*-Methoden halten, die sich an allem oben orientierten, und ...
Aber: Die Dateiausgabe sollte Objektdetails zeigen.
Also landete ich bei:
// 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 Haben Sie sich gefragt, ob Sie das wollten ?
Ich erkunde Winston, um es in meinem Projekt zu verwenden, und frage mich jetzt, ob es sich lohnt, das Risiko einzugehen, da dieses Thema seit mehr als 2 Jahren offen ist. für mich scheint dies eine grundlegende Funktion für jedes Logging-Framework zu sein
Hilfreichster Kommentar
Für uns ist dies eine RIESIGE bahnbrechende Veränderung. Wenn es beabsichtigt ist, sollte es in https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md beschrieben werden