Winston: Melewati beberapa parameter ke fungsi logging tidak berperilaku seperti yang diharapkan

Dibuat pada 6 Agu 2018  ·  43Komentar  ·  Sumber: winstonjs/winston

Tolong beritahu kami tentang lingkungan Anda:

  • _ winston versi?_

    • [ ] winston@2

    • [x] winston@3

  • _ node -v keluaran:_ v8.11.3
  • _Sistem Operasi?_ macOS
  • _Bahasa?_ Alur ES6/7

Apa masalahnya?


Dengan 3.xx:

const winston = require('winston')

const logger = winston.createLogger({
    transports: [new winston.transports.Console()]
})

logger.info('test log', 'with a second parameter')

Keluaran:

{"level":"info","message":"test log"}

Dengan 2.xx:

const winston = require('winston')

const logger = new winston.Logger({
    transports: [new winston.transports.Console()]
})

logger.info('test log', 'with a second parameter')

Keluaran:

info: test log with a second parameter

Apa yang Anda harapkan terjadi sebagai gantinya?


Ini harus menghasilkan:

{"level":"info","message":"test log with a second parameter"}
important

Komentar yang paling membantu

Ini adalah perubahan besar yang menghancurkan bagi kami. Jika disengaja, itu harus dirinci di https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md

Semua 43 komentar

Saya mengalami masalah yang sama hari ini. Saya percaya ini adalah bug karena dokumentasi pemutakhiran juga memiliki contoh seperti itu di sini :

logger.info('transaction ok', { creditCard: 123456789012345 });

Saat ini untuk menyiasatinya, Anda dapat membuat fungsi yang mem-parsing argumen sebelum diteruskan ke winston

@ mulligan121 Oke, tapi saya tidak ingin mengganti setiap pernyataan log di basis kode saya...

@indexzero Apakah ini di bawah radar Anda? Saya pikir ini adalah perubahan besar yang menghancurkan. Ini sebenarnya mencegah perpindahan dari 2.x ke 3.x karena mengharuskan kita untuk mengubah setiap entri log

Solusi sementara:

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);

Ini adalah perubahan besar yang menghancurkan bagi kami. Jika disengaja, itu harus dirinci di https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md

Jadi setelah penyelidikan lebih lanjut, saya menemukan bahwa Anda memerlukan pemformat percikan agar banyak argumen dapat dicetak. Saya pikir itu hanya untuk interpolasi argumen (yaitu hal-hal dengan %s dll. di dalamnya), tetapi tampaknya Anda membutuhkannya hanya untuk melakukan logger.info("something", value) .

Tapi ini masih agak aneh bagi saya - saya mendapatkan sesuatu yang terlihat seperti JSON di output dengan kunci "meta", meskipun saya tidak menggunakan format JSON:

logger.info('Test: %s', 1, 2, 3, 4);

Menghasilkan:

info: Test: 1 {"meta":[2,3,4]}

Bahkan contoh dalam contoh tidak menghasilkan apa yang dikatakannya:

https://github.com/winstonjs/winston/blob/master/examples/interpolation.js#L20 -L21

info: test message first, second {"meta":{"number":123}}

Saya telah menyelesaikannya menggunakan sesuatu di sepanjang baris ini:

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()]
});

Berikut adalah solusi umum untuk memungkinkan beberapa parameter:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29

Berhubungan dengan:
https://github.com/winstonjs/winston/issues/1377

Ada terlalu banyak hal yang tidak bekerja sama.

Hai, Ada pembaruan di sini? Terima kasih.

Juga menunggu cara yang tepat untuk meniru console.log(...args) di winston...

Kami memperbaiki sejumlah kasus tepi/sudut di sekitar splat dan meta di 3.2.0 , tetapi tampaknya ini masih menjadi masalah (lihat: https://github.com /winstonjs/winston/pull/1576 untuk CHANGELOG.md ).

Akan memastikan ini ditangani dalam 3.3.0 . Terima kasih atas kesabaran Anda.

Ini adalah solusi bagi saya:

'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' }),
  ],
});

Ketika saya mencoba masuk dengan argumen, saya mendapatkan hasil yang aneh
var s = "Hello" log.info("asdasda", s)

Mendapatkan keluaran

{"0":"H","1":"e","2":"l","3":"l","4":"o","service":"XXXX","level":"info","message":"asdasda","timestamp":"2019-04-15 13:58:51"}

Saya menggunakan kode mulai cepat yang normal

Satu hal yang saya perhatikan adalah ini:

  • mendapat logger dengan 2 transport (Console dan Rotating file)
  • Keduanya menggunakan format percikan
  • Panggilan ke fungsi transformasi splat untuk transportasi pertama menghapus array yang disimpan pada info di bawah Simbol SPLAT
  • Pada panggilan ke fungsi transformasi splat untuk transportasi kedua, array SPLAT kosong dan dengan demikian argumen tambahan tidak dicatat lagi

Semoga ini bisa/akan diperbaiki

Catatan: menguji ini dengan versi terbaru Winston yang dirilis, melihat sekilas kode tampaknya menunjukkan bahwa itu masih seperti ini di master (yang tampaknya memiliki perbaikan lain)

Beberapa perbaikan atas solusi @luislobo 's 👏

  • Abaikan pesan jika itu gaya percikan yaitu berisi %s %d or %j untuk pesan seperti logger.info(`hello %s`,'world')
  • menyusun ulang formater untuk membuat colorise menjadi yang pertama https://github.com/winstonjs/winston#colorizing -standard-logging-levels
  • Menghapus format twiseObject di printf
  • trimEnd jika argumen tambahan tidak tersedia di looger
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,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()]
});

Adakah pembaruan lebih lanjut untuk ini yang mungkin saya lewatkan? Sepertinya ada dukungan yang cukup kuat untuk fitur ini untuk ditambahkan kembali, tetapi komitmen terakhir untuk ini hampir 6 bulan yang lalu.

Halo, Bumper besar dan penghenti acara, mencoba bermigrasi ke 3.X, mungkin akan mempertahankan 2.x untuk sementara waktu.

Agak kecewa :(

Inilah yang berhasil untuk saya:

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' });

yang menghasilkan: 2019-07-04T21:30:08.455Z [myLabel] info: foo "bar" 1 [2,3] true {"name":"John"}

Pada dasarnya format.combine menetapkan pipa untuk objek info . Untuk setiap fungsi format, transform dipanggil dan pesan log terakhir harus ditulis ke info[Symbol.for('message')]
semoga ini membantu

Saya menginginkan solusi yang mendukung %d , %o dll, tetapi masih default untuk menyertakan argumen lainnya, sehingga logger.info('hello %d %j', 42, {a:3}, 'some', 'more', 'arguments') dirender seperti ini:

hello 42 {"a": 3} some more arguments

Solusi saya untuk ini akhirnya menggunakan simbol splat tetapi secara manual memanggil util.format() langsung dari printf , yang secara default menyertakan argumen istirahat:

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)}`)
    )
})

Jika Anda tidak ingin printf Anda tentu saja dapat menambahkan transformasi yang hanya memperluas argumen menjadi info.message , dan kemudian memformat hasil akhirnya sesuai keinginan Anda:

format: combine(
  {
    transform(info) {
      const {[SPLAT]: args = [], message} = info;

      info.message = format(message, ...args);

      return info;
    }
  },
  simple()
)  

Masalah dengan menggunakan format.splat() adalah bahwa ia menggunakan argumen yang cocok tetapi tampaknya membuang sisanya. Dengan menjalankan util.format() sendiri, saya dapat mengganti perilaku itu.

Masalah yang sama, ada pembaruan tentang yang ini? Saya suka Winston, tetapi itu membuat saya gila ketika saya tidak dapat mencetak semua argumen yang diteruskan ke logger, yang dapat saya lakukan dengan console.log() .

@fr1sk Apakah Anda mencoba pemformatan saya di atas? Ini memberi console.log() seperti perilaku (node console.log() implementasi internal menggunakan util.format() afaik).

Sangat mengecewakan bahwa masalah ini masih belum terselesaikan, dan masalah terkait saya telah dikunci.
Saya bekerja dengan banyak tim berbeda dan mereka semua sama-sama frustrasi karena kehilangan DX sebelumnya saat bermigrasi ke v3.

Saya telah menghabiskan sepanjang hari mencoba berbagai hal.
Solusi di atas sudah dekat tetapi saya melewatkan pewarnaan dan pemutusan garis dari argumen tambahan.

IMO, masuk ke Konsol seharusnya menyenangkan.
Inilah usaha saya untuk mewujudkannya...

pengaturan v2 untuk perbandingan

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'));

Winston2

pengaturan v3

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'));

Winston3

Ada banyak hal yang harus ditangani, beberapa di antaranya

  • Nilai seperti Objek sebagai argumen pertama
  • Beberapa argumen nilai campuran
  • String dengan kode escape ANSI, misalnya menggunakan chalk
  • Nilai esoteris seperti Fungsi dan RegEx
  • Kesalahan sebagai argumen pertama atau di mana saja setelah itu
  • Harus tetap berfungsi dengan baik bersama pemformat lain

Bug saat ini dengan solusi ini

  • Melewati Kesalahan karena argumen pertama tidak mencetak Stack Trace

    • Ini karena info.message hanyalah sebuah string dan saluran tumpukan ada di properti stack

  • Melewati Objek dengan properti message sebagai argumen pertama hanya mencetak message , membuang properti lainnya

    • Alasan yang sama seperti yang di atas

  • Melewati Kesalahan sebagai argumen ke-2 entah bagaimana menggabungkan pesan kesalahan di atas info.message (yang biasanya merupakan nilai argumen ke-1), menghasilkan pesan kesalahan dua kali

    • Dilacak di https://github.com/winstonjs/winston/issues/1660

    • Ini sebenarnya adalah bagian dari README:

      > CATATAN: properti { pesan } apa pun dalam objek meta yang disediakan akan secara otomatis digabungkan ke pesan apa pun yang sudah disediakan: Misalnya, di bawah ini akan menggabungkan 'dunia' ke 'halo':

Bermain-main dengan formatter errors tidak membantu.

Peningkatan positif

  • Mencatat nilai primitif sekarang dipercantik
  • Mencatat beberapa nilai seperti Obyek sekarang menambahkan baris baru di antara mereka
  • Mencatat Array sekarang lebih rapi daripada terlihat seperti Obyek dengan kunci indeks

Sunting:

Kami dapat menangani kesalahan pemformatan tetapi ini meretas:

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}`;
    })
...

ini berfungsi untuk saya menggunakan 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}`;
        })
    )
});

Saya mengerti versi utama memperkenalkan perubahan yang melanggar, tapi ya ampun ...

Tidak ada solusi yang memberi saya perilaku yang sama seperti winston v2.
Solusi dari @henhal dan @yamadashy keduanya memiliki masalah yang sama: nilai pesan ditampilkan sebagai string.
logger.debug(err) buat pesan log:

debug:  Error: ETIMEDOUT

sedangkan logger.debug('anystringhere', err) membuat:

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>

Masalah kedua adalah bahwa argumen tambahan ditekan saat menggunakan dengan level info - winston v3 tampaknya menanganinya dengan cara lain sebelum memformat.

Masalah ketiga adalah ruang yang hilang di antara 2 pesan (perhatikan "anystringhereError").

Konfigurasi logger v3 saya saat ini:

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;

Saya sudah cukup dengan itu dan akan beralih kembali ke winston v2 hanya dengan ini:

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;

Konfigurasi v2 ini tidak memiliki masalah yang disebutkan di atas.

Saya ingin membagikan pengaturan winston saya:

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');

image

Berikut adalah solusi umum untuk memungkinkan beberapa parameter:
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29

di sini adalah tautan yang diperbarui ke solusi yang diusulkan
https://github.com/rooseveltframework/roosevelt/blob/0.13.0/lib/tools/logger.js

Milik saya adalah variasi dari saran bagus

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}`;
    }),
  );
}

untuk log seperti:

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!'));

Ini menghasilkan seperti ini - yang bagus untuk semua skenario saya:

Screen Shot 2020-02-06 at 10 54 31 pm

Hei, saya mulai dengan Winston, tidak pernah menggunakan v2, jadi saya menggunakan v3.2.1

Saya mencoba melakukan:

import winston, { format } from 'winston';
winston.format(format.combine(format.splat(), format.simple()));

winston.info('buildFastify dataPath %s', opts.dataPath);

Dan berharap interpolasi string berhasil; tapi tidak.

{"level":"info","message":"buildFastify dataPath %s"}

Saat aku mengharapkan

{"level":"info","message":"buildFastify dataPath /My/Data/Path"}

Masalah ini adalah hal yang sama entah bagaimana? Atau saya terpaksa menggunakan fungsi logger.log('info', .....) saja?

Sunting

Acara mencoba ini tidak berhasil.

  winston.log('info', 'buildFastify dataPath %s', opts.dataPath);

keluaran:

{"level":"info","message":"buildFastify dataPath %s"}

Terima kasih kepada yang memposting saran di atas.
Sial, saya telah membuang suatu hari hanya untuk mengintegrasikan Winston 3 pada proyek saya:/

Yang ini memukul saya hari ini - saya menyadari logger baru saya yang mewah melemparkan semua argumen ...rest . Ini mungkin tidak berfungsi untuk semua orang atau setiap kasus penggunaan, tetapi dalam kasus saya, saya merasa dapat diterima untuk hanya membungkus semua yang saya inginkan dicatat sebagai array. Ini bukan yang tercantik, tetapi lebih ringan daripada beberapa solusi [sangat pintar] yang membutuhkan lebih banyak kode. Semoga ini bisa membantu orang lain!

logger.info(["Something happened!", foo, bar]);

Benar-benar mengecewakan bahwa mereka memutuskan untuk membuat perubahan besar sebesar ini dan MASIH belum menyebutkannya dalam panduan migrasi atau dokumentasi.

Terlepas dari itu, saya ingin membagikan solusi saya yang menurut saya cukup ringkas dan mengikuti bagaimana node js mengimplementasikan console.log menggunakan 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'),
};

Saya ingin berpadu dan meminta fitur ini untuk ditambahkan ke inti Winston. Saat ini, saya menggunakan pemformat khusus dengan splat untuk mencapai fungsi ini, yang sejujurnya terasa sangat retas. Akan menyenangkan memiliki fungsionalitas yang cocok dengan console.log

Ada pembaruan?

Selain perilaku di atas untuk v3, saya juga ingin menambahkan ini:

logger.info('param 1', { propInJson1: 'propInJson 1', propInJson2: 'propInJson 2' });

akan menghasilkan ini

{"propInJson1":"propInJson 1","propInJson2":"propInJson 2","level":"info","message":"param 1"}

versi yang saya gunakan: (v3.2.1)
Konfigurasi:

winstonLogger.add(new winston.transports.Console());

Saya masih tidak mengerti bagaimana cara menampilkan banyak nilai di Winston.

Saya hanya ingin mengganti console.log('Hello', var1, '!') dengan logger.log('Hello', var1, '!') .

Sejujurnya, mencoba menggunakan Winston selalu menyebabkan banyak waktu terbuang dan masalah mengejutkan dengan logging.

Benar-benar mengecewakan bahwa mereka memutuskan untuk membuat perubahan besar sebesar ini dan MASIH belum menyebutkannya dalam panduan migrasi atau dokumentasi.

Terlepas dari itu, saya ingin membagikan solusi saya yang menurut saya cukup ringkas dan mengikuti bagaimana node js mengimplementasikan console.log menggunakan 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'),
};

Juga, gunakan util.formatWithOptions({ colors: true }, ...args); untuk mendapatkan hasil cetak berwarna seperti console.log

Ini bekerja untuk saya. combineMessageAndSplat yang menggabungkan pesan dan percikan menggunakan 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> 

Saya harus menyesuaikan diri dengan metode console.*, berorientasi pada semua di atas, dan ...

  • metode konsol default (mereka diwarnai secara default) untuk chrome-dev-tools
  • keluaran konsol terminal elektron (juga diwarnai secara default)
  • menulis ke file

Tetapi: Output file harus menunjukkan detail objek.

Jadi saya berakhir dengan:

// 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 Bertanya- tanya apakah Anda masih berencana untuk mengatasi ini di beberapa titik?

saya menjelajahi winston untuk digunakan dalam proyek saya, sekarang bertanya-tanya apakah layak mengambil risiko karena masalah ini terbuka selama lebih dari 2 tahun. bagi saya ini sepertinya fungsi dasar untuk kerangka kerja logging apa pun

Apakah halaman ini membantu?
0 / 5 - 0 peringkat