Winston log to file not working - node.js

I use Winston for logging:
var winston = require('winston');
var logger = new(winston.Logger)({
transports: [
new(winston.transports.Console)(),
new(winston.transports.File)({filename: '/var/log/logF.log'})
]
});
and I write to this log:
logger.log("File: " + path + " was found");
For some reason, the file /var/log/logF.log isn't updated, and also the standard output isn't shown the log.
How do I use it so the log will be written in '/var/log/logF.log'?

You haven't specified a log "level", and "log" is unfortunately not a default level.
Try:
logger.log("info", "File: was found");
// or
logger.info("File: was found");

After trying and made severals tests with severals advanced logging mechanisms (incl. winston, bunyan, log4js), it appears that loggers are not able to write into file if you do a clean exit process.exit(0).
Removing clean exit solve the problem for me.

I had this issue this evening. However, I realized the file location wasn't being resolved. I'm not sure if this will solve your issue.
filename: path.resolve(__dirname, "add_your_relative_path/error.log")

Related

Structured Logs in Google Cloud Run not being parsed (using Winston for logging)

I'm attempting to format my logs in such a way that Google Cloud will correctly extract the log level. This is running on Cloud Run, with typescript. Cloud Run is grabbing the logs from the container output.
If I do the following, google correctly parses the log line:
console.log(JSON.stringify({
severity: 'ERROR',
message: 'This is testing a structured log error for GCP'
}));
And the log output looks like this:
I've tried a number of different ways to format with winston, ended up with the following:
useFormat = format.combine(
format((info, opts) => {
info['severity'] = info.level;
delete info.level;
return info;
})(),
format.json());
this.winston = winston.createLogger({
level: logLevel,
format: useFormat,
transports: [new winston.transports.Console()]
});
Which looks like it will work (it correctly outputs the json line), I get this in the GCP logs:
Any help appreciated.
Turns out I was close, just needed to .upperCase() the log level (and I'm mapping Verbose -> Debug, I don't really understand why GCP decided to do a totally different log leveling system than everyone else). New code:
useFormat =
format.combine(
format((info, opts) => {
let level = info.level.toUpperCase();
if(level === 'VERBOSE') {
level = 'DEBUG';
}
info['severity'] = level;
delete info.level;
return info;
})(),
format.json());
The last bit of the question is confusing. The problem OP is pointing to is that the json is printed out and the severity is default. The json should not be printed out, only the message, and the severity should be debug. The answer that OP provides does what is wanted.
For others that may be confused in the same way I was.

Log all errors and warnings

I am using a third party nodejs application which is quite large and it is using many different things for logging. For instance console.log() and console.error(). I would like to be able to trap all output and log to a specific file. I was thinking about using winston and do something like this:
const winston = require('winston')
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' })
]
})
const ce = console.error
console.error = function(...args) {
logger.log.apply('error', args)
ce.apply(args)
}
Is there a better way to handle this kind of situation?
I might also add that some parts of the application is already using winston for logging purposes.
My aim is the create a single file with all errors and warnings generated from within the application.

NodeJS - WinstonJS - Clear the log file

I'm using WinstonJS for logging to a file, and nodemon to restart when I update my code.
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
level: 'silly',
filename: __dirname + '/logs/test.log',
json: false
})
]
});
logger.log('info', 'something');
The log file is being appended to, however when I make a code change and save my file, nodemon runs it again and the log file is appended to again. This leads to a log file that just keeps getting longer and longer, and I have to keep manually deleting the contents.
I guess I could do something with the fs module, but it would be far nicer to use Winston to say something like update: replace|append, but I can't see anything like that available.
Is there any way to clear the log file, so I only have log entries for the last time my code was run..?
The
{ flags: 'w' }
property on the options object on the new transport is working for me:
transports: [
new winston.transports.File({ filename: 'myLog.txt', options: { flags: 'w' } })
]
I know this question is a little outdated, but I recently found the answer to this and thought I would share it here for posterity. You can pass fs.createWriteStream options to the File logger:
// Open the file in "write" mode, which truncates first
options: { flags: 'w' },

where is log file in nodejs app with winston

I can not find in my app directory where is 'test.log' file?
below code is in server.js
var winston = require('winston'), mylogger = new (winston.Logger)({
transports: [
new (winston.transports.Console) (),
new (winston.transports.File) ({filename: 'test.log'})
]
});
mylogger.log('Hello world');
my app directory:
/
app/
config/
public/
server.js
Interesting question. Looking at the source code for the file transport, it appears that the directory, if not specified, is derived from the filename parameter itself. It seems to suggest that you either use an absolute path or relative path with a directory explicitly specified.
This line is where it figures out the absolute path.
var fullname = path.join(self.dirname, target);
self.dirname is setup here:
this.dirname = options.dirname || path.dirname(options.filename);
so the question is that if options.filename does not include a directory, what does path.dirname return?
I do not actually know, but there are two possibilities I would suspect:
Current working directory of the process
The file system root, because if path.dirname takes what is left of the last /, then it is undefined and undefined + '/test.log' is '/test.log'
There are two steps you can take:
Check the current directory and file system root to see which it is. (in other words, test the theories)
Specify the directory explicitly (probably a good idea anyway)
https://github.com/flatiron/winston/blob/master/lib/winston/transports/file.js
I wrote a test file like this:
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'somefile.log' })
]
});
logger.log('info', 'Hello distributed log files!');
logger.info('Hello again distributed logs');
process.exit();
and I found that if I deleted the last line, the log file would be created and logged correctly.
I used process.exit() to break my program as I just wanted to test the logger, and it looked like it somehow broke the process on log file as well.
Check this issue: https://github.com/winstonjs/winston/issues/228

Is there an equivalent of log.IsDebugEnabled in Winston?

Is there an equivalent of log.IsDebugEnabled in Winston?
I want to use this to skip expensive logging code in a production environment but have it execute in development.
For example:
if(winston.isDebugEnabled){
// Call to expensive dump routine here
dump();
}
Checking winston.debug just checks whether the method is defined, not whether it is enabled.
Many thanks!
Edit: Added code example.
I've added a method to my logger to achieve just that:
logger.isLevelEnabled = function(level) {
return _.any(this.transports, function(transport) {
return (transport.level && this.levels[transport.level] <= this.levels[level])
|| (!transport.level && this.levels[this.level] <= this.levels[level]);
}, this);
};
This goes through each of your logger's transports and checks whether it 'wants' to log the specified level.
Note _.any is lodash, you can replace with for loop.
I'm sure you'd be able to get that directly from winston, but if you want to have different logging levels for different environments, you should pass these in when you're creating the winston.logger.
For example:
// default log file level is info (which is the lowest by default)
var logFileLevel = 'info';
if (process.env.NODE_ENV == 'production') {
// only write logs with a level of 'error' or above when in production
logFileLevel = 'error';
}
var logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
filename: '/var/log/node-logger.log',
level: logFileLevel
})
]
});
It's also useful to switch out the transports. You might want to use the Console transport whilst in development, and the File transport when in production for example.
More documentation on all this on the winston readme.
Try
if ( logger.levels[logger.level] >= logger.levels['debug'] ) {
// expensive calculation here
logger.debug(...)
}
Since Winston 3.1.0 (PR), you can use the Logger functions isLevelEnabled(string) & isXXXEnabled() for this.

Resources