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' },
Related
I am trying to create a daily rotating log with log entries from throughout the application as well as uncaught exceptions:
const { createLogger, format, transports } = require('winston')
import 'winston-daily-rotate-file'
const httpContext = require('express-http-context')
const requestIdFormat = format((info, opts) => {
const requestId = httpContext.get('requestId')
if (requestId){
info.requestId = requestId
}else{
info.requestId = ''
}
return info
})
const allTransport = new transports.DailyRotateFile({
filename: 'logs/%DATE%-application.log',
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxFiles: '14d',
level: 'info',
handleExceptions: true
})
const errorTransport = new transports.DailyRotateFile({
filename: 'logs/%DATE%-error.log',
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxFiles: '14d',
level: 'error',
handleExceptions: true
})
export const logger = createLogger({
format: format.combine(requestIdFormat(), format.timestamp(), format.printf(i => `${i.timestamp} | ${i.requestId} | ${i.level}: ${i.message}`), format.errors({stack: true})),
transports: [
allTransport,
errorTransport,
],
exitOnError: false
})
But the exceptions e.g. throw Error('hello?') are not logged to the log files.
I've tried other variations c.f. https://github.com/winstonjs/winston#handling-uncaught-exceptions-with-winston e.g. setting exceptionHandlers in createLogger, but that does not work either.
How should I alter the code to include uncaught exceptions in the log?
UPDATE: I now see that an exception thrown on e.g. invalid import IS in fact logged, so maybe the issue is that the exception I test with is thrown in an express service - maybe it is caught in the express framework and that is why it is not logged?
Thanks,
-Louise
I ended up just "manually" logging exceptions, i.e. logger.error(err), as I already have a middleware hook for showing a catch-all error page.
I am still not sure why some exceptions were automatically logged and why I have to manually log exceptions I explicitly throw via "throw new Error('some message')"?
I've faced this kind of situation before, and for some reason, sometimes the node process get killed/exited before all log handling finishes its execution. There are some libs that may cause conflict in handling because they may call process.exit() while other libs are trying to handle the same thing. So, we need to investigate and debug to try to find what is terminating our process before our logs are flushed/written to disk. I strongly recommend not doing any async processing when caughting exceptions. Do everything in a sync way and faster.
In a project I've worked, I spended hours until I found process.exit in a module , probably copied from internet. Process.exit been called everywhere in an app is the root cause for errors and misbehavior of apps.
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.
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")
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
I am using Winston logging with my Node.js app and have defined a file transport. Throughout my code, I log using either logger.error, logger.warn, or logger.info.
My question is, how do I specify the log level? Is there a config file and value that I can set so that only the appropriate log messages are logged? For example, I'd like the log level to be "info" in my development environment but "error" in production.
If you are using the default logger, you can adjust the log levels like this:
const winston = require('winston');
// ...
winston.level = 'debug';
will set the log level to 'debug'. (Tested with winston 0.7.3, default logger is still around in 3.2.1).
However, the documentation recommends creating a new logger with the appropriate log levels and then using that logger:
const myLogger = winston.createLogger({
level: 'debug'
});
myLogger.debug('hello world');
If you are already using the default logger in your code base this may require you to replace all usages with this new logger that you are using:
const winston = require('winston');
// default logger
winston.log('debug', 'default logger being used');
// custom logger
myLogger.log('debug', 'custom logger being used');
Looks like there is a level option in the options passed covered here
From that doc:
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ level: 'error' }),
new (winston.transports.File)({ filename: 'somefile.log' })
]
});
Now, those examples show passing level in the option object to the console transport. When you use a file transport, I believe you would pass an options object that not only contains the filepath but also the level.
That should lead to something like:
var logger = new (winston.Logger)({
transports: [
new (winston.transports.File)({ filename: 'somefile.log', level: 'error' })
]
});
Per that doc, note also that as of 2.0, it exposes a setLevel method to change at runtime. Look in the Using Log Levels section of that doc.
There are 6 default levels in winston: silly=0(lowest), debug=1, verbose=2, info=3, warn=4, error=5(highest)
While creating the logger transports, you can specify the log level like:
new (winston.transports.File)({ filename: 'somefile.log', level: 'warn' })
Above code will set log level to warn, which means silly, verbose and info will not be output to somefile.log, while warn, debug and error will.
You can also define your own levels:
var myCustomLevels = {
levels: {
foo: 0,
bar: 1,
baz: 2,
foobar: 3
}
};
var customLevelLogger = new (winston.Logger)({ levels: myCustomLevels.levels });
customLevelLogger.foobar('some foobar level-ed message');
Note that it's better to always include the 6 predefined levels in your own custom levels, in case somewhere used the predefined levels.
You can change the logging level in runtime by modifying the level property of the appropriate transport:
var log = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ level : 'silly' })
]
});
...
// Only messages with level 'info' or higher will be logged after this.
log.transports.Console.level = 'info';
I guess, it works similarly for file but I haven't tried that.
If you want to change the log level on the fly. Like for when you need to trace production issue for short amount of time; then revert to error log level. You can use a dynamic logger provided you can expose a service on the web https://github.com/yannvr/Winston-dynamic-loglevel
apart from this you can cleanly achieve this by imlplementing runtime-node-refresh follow this link for more.