Winston: `this._addDefaultMeta` bukan sebuah fungsi

Dibuat pada 28 Jan 2019  ·  22Komentar  ·  Sumber: winstonjs/winston

Beri tahu kami tentang lingkungan Anda:

  • _ winston versi? _

    • [] winston@2

    • [x] winston@3

  • _ node -v keluaran: _ 8.9.3
  • _Sistem operasi? Linux & Mac
  • _Language? _ Es6

Apa masalahnya?

Sejak rilis 3.2.0 kami mendapatkan yang berikut ini:

error: this._addDefaultMeta is not a function {"stack":"TypeError: this._addDefaultMeta is not a function\n    at APIClient.(anonymous function) [as logger] (/Users/erriettakostala/prototype1/server/node_modules/winston/lib/winston/create-logger.js:55:16)\n  

Kami hanya menelepon log dengan cara yang sama seperti sebelumnya.

  const logger = winston.createLogger({
    level: process.env.LOG_LEVEL || 'debug',
    format: process.env.NODE_ENV === 'production' ? winston.format.json() : winston.format.simple(),
    transports: [ new winston.transports.Console() ]
  })

logger.log({
  level: 'info',
  message: ''
});

Apa yang Anda harapkan terjadi?

Kode agar tidak macet :-)

bug help wanted important

Komentar yang paling membantu

Saya kira kita perlu menggunakan fungsi panah di sana, itu autobinds. Akan mencoba memberikan PR untuk ASAP itu.

Semua 22 komentar

Jadi itu mungkin salah kita. Saya hanya dapat mereproduksi ini jika kita melakukan:

const log = logger.debug;
log('test');

logger.debug('test') baik-baik saja

Benar, jadi ini terjadi karena fungsi tidak terikat ke this dalam kasus penggunaan seperti itu. Tidak yakin apakah itu penggunaan yang benar karena tidak ada janji untuk salah satu fungsi logger menjadi fungsi murni tanpa status. Ini juga akan berfungsi jika Anda melakukan const log = logger.debug.bind(logger)

Saya tidak yakin dalam kasus ini, karena kasus penggunaan seperti itu bisa menjadi tipikal saat menggunakan winston sebagai logger khusus. Dalam kasus saya, saya menggunakannya sebagai logger khusus untuk SailsJS dan hingga 3.2.0 semuanya berfungsi dengan baik: - /

Kode saya:

const logger = createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: combine(timestamp(), format.json()),
  transports: [new transports.Console()],
})

module.exports.log = {
  custom: logger,
}

Saya kira kita perlu menggunakan fungsi panah di sana, itu autobinds. Akan mencoba memberikan PR untuk ASAP itu.

Upaya maju yang cepat untuk memperbaiki tampaknya merusak barang-barang. Diperlukan penyelidikan lebih lanjut.

Anda dapat melihatnya di sini: https://github.com/kibertoad/winston/tree/fix/autobind-for-functions

Jika Anda memiliki ide mengapa hal itu merusak fungsi logger anak, saya akan senang mendengarnya.

apakah karena child menghasilkan const logger = this; ?
(benar-benar membuang barang ke dinding)

Halo semuanya - terima kasih telah melaporkan ini. Saya telah memperhatikannya secara sepintas ketika menulis tes yang tidak terkait untuk 3.2.0 , tetapi tidak menyadari itu adalah regresi dari 3.1.0 .

Regresi itu sendiri diperkenalkan pada # 1483. Sangat berterima kasih @soldair menambahkan cakupan pengujian untuk skenario tersebut karena memperbaiki ini akan memperkenalkan regresi lain tanpa <3.

1579 merupakan upaya untuk memperbaiki masalah ini. Saat ini tampaknya netral dari perspektif kinerja _ (yay) _, tapi sayangnya bukan solusi yang paling jelas, langsung, atau "elegan" _ (boo) _.

Mengingat bahwa https://github.com/winstonjs/winston/pull/1539 diabaikan sebesar 3.2.0 , jika kita bisa mendapatkan beberapa 👀👀👀dari orang-orang di # 1579 dan mereka 👍 maka kita harus baik-baik saja bentuk untuk mendorong 3.2.1 besok 💯✨🎉

Mungkin kesalahan terkait yang saya lihat:

Cannot read property '_addDefaultMeta' of undefined

Iya. Itu adalah kesalahan yang sama. Terima kasih telah melaporkan!

Saya masih mendapatkan masalah serupa setelah memperbarui ke 3.2.1. Saya menggunakan NestJS dan memiliki layanan logger khusus yang membuat logger dan kemudian menetapkan properti kelas untuk dipetakan terhadap metode logger.
misalnya
const logger = winston.createLogger (....);
this.log = logger.log;
this.error = logger.error;
this.warn = logger.warn;

dll.

Saat mencoba masuk, dapatkan TypeError: this.write bukan sebuah fungsi
Mencoba mengubah ke
this.error = logger.error.bind (logger);

Yang sekarang akan mencatat tanpa kesalahan, tetapi kemudian tidak mencatat metadata.
misalnya log.error ('aaa', {abc: 'abc'}) hanya akan mengeluarkan 'aaa' dan tidak ada yang lain.

@ ColinMorris83 Bisakah Anda membuat PR dengan tes gagal di https://github.com/winstonjs/winston/blob/master/test/logger.test.js? (sesuatu yang mirip dengan defaultMeta() autobinds correctly saya bayangkan)
Saya bertanya-tanya seberapa berbeda kasus Anda dengan kasus yang dicakup oleh tes (yang berhasil).

Hai @kibertoad ,
Saya dapat membuat pengujian yang gagal dengan yang berikut ini, meskipun itu bukan kesalahan yang sama yang saya dapatkan saat menggunakannya di Nest.
Saya menambahkan ini ke bagian bawah logger.test.js

it('defaultMeta() autobinds correctly when using a class', () => {
    class LoggingService {
      constructor() {
        var logger = winston.createLogger({
          level: 'info',
          exitOnError: false,
          transports: []
        });
        this.info = logger.info;
      }
    }

    const service = new LoggingService();
    service.info('test');
  });

Yang memberi sebagai berikut:
1) Harus mendukung penebang anak & defaultMeta
defaultMeta () autobind dengan benar saat menggunakan kelas:
TypeError Tidak Tertangkap: self._addDefaultMeta bukan sebuah fungsi
di LoggingService.DerivedLogger. (fungsi anonim) [sebagai info] (lib / winston / create-logger.js: 39: 371)
di Context.it (test / logger.test.js: 1096: 13)

Mengubah baris menjadi this.info = logger.info.bind (logger); lulus ujian. Namun, kemudian saya pikir itu akan mengarah ke masalah metadata berikutnya yang tidak menghasilkan, tetapi saya tidak yakin bagaimana cara mengujinya di unit test

Ada banyak permutasi yang hampir tidak ada habisnya dari pengikatan this yang dapat terjadi. Yang didukung secara resmi adalah:

  1. Sebuah instance Logger .
  2. Tidak ada

misalnya untuk tes Anda yang gagal, Anda bisa saja memiliki LoggingService mewarisi dari Logger misalnya:

Gunakan Object.create

it('defaultMeta() autobinds correctly when using a class', () => {
  var logger = winston.createLogger({
    level: 'info',
    exitOnError: false,
    transports: []
  });

  const service = Object.create(logger);
  service.info('test');
});

Ikat dengan benar this

it('defaultMeta() autobinds correctly when using a class', () => {
  class LoggingService {
    constructor() {
      var logger = winston.createLogger({
        level: 'info',
        exitOnError: false,
        transports: []
      });

      // Either bind to the logger
      this.info = logger.info.bind(logger);

      // Or pass through the arguments
      this.info = (...args) => logger.info(...args);
    }
  }

  const service = new LoggingService();
  service.info('test');
});

jika kode Anda berfungsi sebelumnya, itu adalah efek samping yang tidak diinginkan dari regresi yang lebih besar yang tidak terselesaikan. Ini adalah hal yang sulit untuk dilakukan dengan benar.

Terima kasih @indexzero
Jadi jika mengubah untuk mengikat ke logger seperti ini:
this.info = logger.info.bind (logger);

Setelah melakukan ini, metadata tidak mendapatkan keluaran, apakah itu bug atau saya salah menggunakannya.
misalnya dalam kasus saya di atas, itu akan menjadi:

service.info ('test', {somemeta: 'something'});

Dimengerti. Mungkin saya salah. Teknik kedua benar-benar akan berhasil:

it('defaultMeta() autobinds correctly when using a class', () => {
  class LoggingService {
    constructor() {
      var logger = winston.createLogger({
        level: 'info',
        exitOnError: false,
        transports: []
      });

      // Pass through the arguments
      this.info = (...args) => logger.info(...args);
    }
  }

  const service = new LoggingService();
  service.info('test');
});

Masih belum ada metadata yang dicatat saat menggunakan cara tembus juga.
Mungkin bisa jadi fungsi format saya perlu diperbarui, karena ketika saya konsol log objek info yang masuk ke dalamnya, ia tidak memiliki properti meta.

const formatFunction = (info) => {
      const logMessage = `${info.timestamp} [${info.level}] ${(info.message ? info.message : '')}
      ${(info.meta && Object.keys(info.meta).length ? `\n${JSON.stringify(info.meta, null, 2)}` : '')}`;
      return logMessage.replace(/\n(?=\S)/g, '\n ');
    };

Objek info adalah ini:

{ somemeta: 'something',
  level: '\u001b[32mINFO\u001b[39m',
  message: 'App is running:',
  timestamp: '2019-01-30T14:17:46.850Z',
  [Symbol(level)]: 'info',
  [Symbol(splat)]: [ { somemeta: 'something' } ] }

Saya menduga ini tidak ada hubungannya jika kita turun ke tingkat debugging fungsi format Anda.

Hal terburuk terkait masalah ini adalah ketika Anda menulis data pada database dengan ORM garis air. Saya akhirnya menyerah menggunakan pencampuran winston.js dan sails.js,

maaf saya salah sambung. :(

Saya harus menulis komentar ini untuk masalah lain

@sapsaldog Bagi saya ini terdengar seperti sesuatu yang harus ditangani oleh sails.js, bukan winston.

Saya menduga ini tidak ada hubungannya jika kita turun ke tingkat debugging fungsi format Anda.

Ya saya pikir mungkin tidak terkait dengan masalah awal, meskipun saya curiga bisa menjadi bug yang diperkenalkan di suatu tempat karena pada 3.1.0 objek info memiliki properti meta, dari 3.2.0 tidak ada. Saya akan mencoba mencari waktu untuk melihat apakah semuanya berfungsi dengan baik saat menggunakan winston sebagai modul yang diperlukan normal, mengambil penggunaan kelas dan NestJ keluar dari persamaan.

Bukan serangga. Sesuai desain. Perubahan melanggar dari logform@1 menjadi logform@2 . Lihat: https://github.com/winstonjs/logform/blob/master/CHANGELOG.md#new -splat-behaviour

Perilaku tidak konsisten, memilih untuk menyebarkan semua properti. Jika Anda ingin "tidak terbaca" menggunakan https://github.com/winstonjs/logform#metadata

Ya, baru saja melihat hal itu di changelog, saya akan melihat dokumen metadata yang Anda tautkan juga. Terima kasih

Apakah halaman ini membantu?
0 / 5 - 0 peringkat