Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.0.0 winston.query throws exception for File Transport #1130

Open
Kouzukii opened this issue Nov 6, 2017 · 15 comments
Open

3.0.0 winston.query throws exception for File Transport #1130

Kouzukii opened this issue Nov 6, 2017 · 15 comments
Labels
Bug Good First Issue Good issue for new contributors Help Wanted Additional help desired from the community winston-file Issues to move to `winston-file` when we create it

Comments

@Kouzukii
Copy link
Contributor

Kouzukii commented Nov 6, 2017

The Functions Transport.prototype.normalizeQuery, Transport.prototype.formatResults and common.clone were removed in 3.0.0, so query will throw an unhandled exception.

@Kouzukii Kouzukii changed the title winston.query throws exception for File Transport 3.0.0 winston.query throws exception for File Transport Nov 6, 2017
@Kouzukii
Copy link
Contributor Author

Kouzukii commented Nov 6, 2017

For others that have the same problem here is a temporary hack that lets query() work as intended.

// TODO REMOVE WHEN FIXED
// necessary workarounds for winston 3.0.0-rc1..

function clone(obj) {
    var copy = Array.isArray(obj) ? [] : {};
    for (var i in obj) {
        if (Array.isArray(obj[i])) {
            copy[i] = obj[i].slice(0);
        } else if (obj[i] instanceof Buffer) {
            copy[i] = obj[i].slice(0);
        } else if (typeof obj[i] != 'function') {
            copy[i] = obj[i] instanceof Object ? clone(obj[i]) : obj[i];
        } else if (typeof obj[i] === 'function') {
            copy[i] = obj[i];
        }
    }
    return copy;
}
require("winston/lib/winston/common").clone = clone;

let Transport = require("winston-transport");
Transport.prototype.normalizeQuery = function (options) {  //
    options = options || {};

    // limit
    options.rows = options.rows || options.limit || 10;

    // starting row offset
    options.start = options.start || 0;

    // now
    options.until = options.until || new Date;
    if (typeof options.until !== 'object') {
        options.until = new Date(options.until);
    }

    // now - 24
    options.from = options.from || (options.until - (24 * 60 * 60 * 1000));
    if (typeof options.from !== 'object') {
        options.from = new Date(options.from);
    }

    // 'asc' or 'desc'
    options.order = options.order || 'desc';

    // which fields to select
    options.fields = options.fields;

    return options;
};
Transport.prototype.formatResults = function (results, options) {
    return results;
};

@emiliobucha
Copy link

Thanks @Kouzukii, I had to do the same, taking as an example the v 2.x.

@indexzero indexzero added Bug Good First Issue Good issue for new contributors Help Wanted Additional help desired from the community labels Apr 26, 2018
@mayeaux
Copy link

mayeaux commented May 22, 2018

@Kouzukii , this blows up for me:

{ file: SyntaxError: Unexpected token l in JSON at position 2
    at JSON.parse (<anonymous>)
    at add (node_modules/winston/lib/winston/transports/file.js:223:22)
    at ReadStream.<anonymous> (node_modules/winston/lib/winston/transports/file.js:203:9)
    at ReadStream.emit (events.js:159:13)
    at addChunk (_stream_readable.js:265:12)
    at readableAddChunk (_stream_readable.js:248:13)
    at ReadStream.Readable.push (_stream_readable.js:209:10)
    at onread (fs.js:2115:12)
    at FSReqWrap.wrapper [as oncomplete] (fs.js:676:17) }

@mirkojotic
Copy link

@indexzero I'd like to work on this but I'm unsure of the direction. There must have been a reason for removing some of these functions. Should I reuse 2.x code or did you have something else in mind.

@jnreynoso
Copy link

How to use this hack?

@Kouzukii
Copy link
Contributor Author

Kouzukii commented Aug 15, 2018

Hey since there's some unclarity here,
You have to put the code I posted above into a JavaScript-file (let's call it winston-workaround.js)

And at the very top of your app.js (the JavaScript file you're starting with npm start) you put

require('./winston-workaround');
// or with babel
import './winston-workaround'

And the example posted by the Winston team should work (tested with winston 3.0.0).

If I get some time soon, I'll open a pull request that resolves this issue.

@jnreynoso
Copy link

Thank you @Kouzukii, I did what you recommended

winston-workaround.js

// TODO REMOVE WHEN FIXED
// necessary hacks for winston 3.0.0-rc1..

function clone (obj) {
  var copy = Array.isArray(obj) ? [] : {}
  for (var i in obj) {
    if (Array.isArray(obj[i])) {
      copy[i] = obj[i].slice(0)
    } else if (obj[i] instanceof Buffer) {
      copy[i] = obj[i].slice(0)
    } else if (typeof obj[i] !== 'function') {
      copy[i] = obj[i] instanceof Object ? clone(obj[i]) : obj[i]
    } else if (typeof obj[i] === 'function') {
      copy[i] = obj[i]
    }
  }
  return copy
}

require('winston/lib/winston/common').clone = clone

let Transport = require('winston-transport')

Transport.prototype.normalizeQuery = function (options) {
  options = options || {}

  // limit
  options.rows = options.rows || options.limit || 10

  // starting row offset
  options.start = options.start || 0

  // now
  options.until = options.until || new Date()
  if (typeof options.until !== 'object') {
    options.until = new Date(options.until)
  }

  // now - 24
  options.from = options.from || (options.until - (24 * 60 * 60 * 1000))
  if (typeof options.from !== 'object') {
    options.from = new Date(options.from)
  }

  // 'asc' or 'desc'
  options.order = options.order || 'desc'

  // which fields to select
  options.fields = options.fields

  return options
}

Transport.prototype.formatResults = function (results, options) {
  return results
}

and this is my entry point

require('./tools/winston-workaround')

/* Core Libraries  */
import chokidar from 'chokidar'
import chalk from 'chalk'
import fs from 'fs'
import path from 'path'
import moment from 'moment'

/* App Libraries */
import { db } from './database'
import upload from './upload'

/* App Config */
import { logger } from './tools'
import CONFIG from '../config.json'


const { AWS: { S3: S3Config } } = CONFIG

const Op = db.Sequelize.Op
...
..
.
const options = {
   from: global.processTimeStart,
   until: timeEnd
}

logger.query(options, (err, results) => {
  if (err) {
    throw err
  }

  console.log(results)
 })

but I still have the same error TypeError: clone is not a function, will it be maybe my winston configuration?.

@jnreynoso
Copy link

jnreynoso commented Aug 15, 2018

This is my winston configuration

logger/index.js

import { createLogger, format, transports } from 'winston'
import path from 'path'
import moment from 'moment'

// import CustomTransport from './customTransport'

import stripAnsi from 'strip-ansi'

import CONFIG from '../../config.json'

const { combine, printf } = format

const frmtLog = printf(info => {
  // Remove Colors Characters
  const level = stripAnsi(info.level)
  const message = stripAnsi(info.message)

  const now = moment(info.timestamps).format('YYYY-MM-DD hh:mm:ss')

  return `[${now}] ${level}: ${message}`
})

const logger = createLogger({
  format: combine(
    frmtLog
  ),
  transports: [
    new transports.File({
      filename: path.join(CONFIG.LOGS, 'info.log'),
      level: 'info'
    }),
    new transports.File({
      filename: path.join(CONFIG.LOGS, 'warning.log'),
      level: 'warning'
    }),
    new transports.File({
      filename: path.join(CONFIG.LOGS, 'error.log'),
      level: 'error'
    }),
    new transports.File({
      filename: path.join(CONFIG.LOGS, 'combined.log')
    })
  ]
})

if (process.env.NODE_ENV !== 'production') {
  logger.add(new transports.Console({
    format: format.combine(
      format.colorize({
        all: true
      }),
      format.simple()
    )
  }))
}

@Kouzukii
Copy link
Contributor Author

@jnreynoso that's interesting, I just tried this with Babel and it seems that babel sorts the import instructions to be above the require() instruction, so clone isn't set by the workaround before Winston is loaded.
To fix this, simply change the

require('./winston-workaround');

to

import './winston-workaround'

@jnreynoso
Copy link

thank you very much @Kouzukii. Your solution worked correctly.

@brunottonurb
Copy link

brunottonurb commented Nov 13, 2020

This issue is still happening as of v3.3.3. Or why is it still open?

@backflip
Copy link

It is still open for libraries like winston-mongodb which are depending on normalizeQuery being exposed on the instance: https://github.com/winstonjs/winston-mongodb/blob/9adea8ad3111ad02e97e004b9cdd0a0d497ba9e4/lib/winston-mongodb.js#L253

@Chukstart
Copy link

Work-around works perfectly though when will this be brought back was it removed unintentionally?

@Chukstart
Copy link

Why won't this get fixed?

@wbt
Copy link
Contributor

wbt commented Jun 22, 2022

Lack of any budget at all for maintenance of this project, lack of any PRs for a fix and/or anti-regression test to review even if there were more resources available for that, and presence of an existing workaround which probably eliminates the motivation for potential PR authors, all likely play a role.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Good First Issue Good issue for new contributors Help Wanted Additional help desired from the community winston-file Issues to move to `winston-file` when we create it
Projects
None yet
Development

No branches or pull requests

10 participants