winstonjs / winston

A logger for just about everything.
http://github.com/winstonjs/winston
MIT License
22.79k stars 1.81k forks source link

[Bug]: Winston won't create log file using File transport #2250

Open timpaulaskas opened 1 year ago

timpaulaskas commented 1 year ago

🔎 Search Terms

Won't Create File

The problem

I can get the console transport to work and this create the Logs directory, but it doesn't create any log files and doesn't provide any error information.

What version of Winston presents the issue?

v3.8.2

What version of Node are you using?

v19.2.0

If this worked in a previous version of Winston, which was it?

No response

Minimum Working Example


const logger = createLogger({
    level: 'debug',
    exitOnError: false,
    format: format.combine(format.splat(), format.simple(), format.json()),
    transports: [
        new transports.File({ filename: `${global.__basedir}/logs/error.log` })
    ]
});

logger.add(new transports.Console({
    format: format.combine(
        format.colorize(),
        format.simple()
    )
}));

module.exports = logger;

// Example logs
logger.log('info', 'Hello simple log!');
logger.info('Hello log with metas', { color: 'blue' });

Additional information

No response

wbt commented 1 year ago

Do you get what you expect if you

console.log(`${global.__basedir}/logs/error.log`)

at the top of the file?

Hufschmidt commented 1 year ago

I think I just observed a similar or related error as well:

So the issue (at least on my part) seems to stem from trying to log to a directory outside the script directory.


Also unlike for example #1958, I'm not using process.exit(...) but let the script exit normally and set process.exitCode = ... instead!

Hufschmidt commented 1 year ago

I found the culprit to be that the File-Transport expect its filename parameter to be a file relative to its other (optional) parameter dirname, as the transport will do join(dirname, filename) to determine the actual path of the requested logfile target throughout its code.

But when you use an absolute path in filename (without also setting dirname) this join will of course fail, since eg. filename: /var/log/script.log will be incorrectly joined to /var/log/var/log/script.log.

Workaround: Set dirname: /var/log/ and filename: script.log (or in the initial example: dirname: ${global.__basedir}/logs/ and filename: error.log)

Solution: Fix all joins in https://github.com/winstonjs/winston/blob/master/lib/winston/transports/file.js to ignore dirname when filename is an absolute path, or (better) use this._basename instead of this.filename for the joins!

Hufschmidt commented 1 year ago

Workaround confirmed to work:

const logger = createLogger({
    level: 'debug',
    format: format.combine(format.splat(), format.simple(), format.json()),
    transports: [
        new transports.File({ 
            filename: 'error.log',
            dirname: `${global.__basedir}/logs`,
        })
    ]
});

logger.add(new transports.Console({
    format: format.combine(
        format.colorize(),
        format.simple()
    )
}));

module.exports = logger;

// Example logs
logger.log('info', 'Hello simple log!');
logger.info('Hello log with metas', { color: 'blue' });

Also an update/notice about dirname vs filename to the documentation might be a good idea.

jaydub2099 commented 1 year ago

Wanted to note that I ran into this as well and adding the dirname property to go along with the filename property for the transport fixed my issue. Given that dirname was not in the docs for the File transport, would not have known to try this.

DABH commented 1 year ago

PR even just for docs would be greatly welcomed and appreciated!!!