How do I log Socket.io through Winston? - node.js

I would like to use Winston as logger for Socket.io. I have seen this issue where it says:
var io = require('socket.io').listen(8080);
io.set('logger', { debug: <log function>, info: … , error: .., warn: .. })
Unfortunately, it is not described what the log function should look like.
Some playing around and a look into the Socket.io logger documentation told me that there is no fixed set of parameters: There are log messages with one, two and three parameters. Perhaps there are even more, I don't know.
I think that this is definitely not a good practice to have an undefined number of parameters, especially if this is your interface to external components.
Anyway ... does anybody have some experience with this? Can anyone point out what to watch out for?

This seems to work fine for me
var io = require('socket.io').listen(server, {
logger: {
debug: winston.debug,
info: winston.info,
error: winston.error,
warn: winston.warn
}
});
As a bonus, by setting the logger in the same call as .listen(), you catch all the log output from Socket.IO. Note that you should be able to just pass winston instead of that object, but it isn't working for me, so that's why I've posted this solution instead.

Since socket.io v1.0 logger parameter does not longer work.
They switched to debug
You may refer to this issue on how to setup Winston with socket.io

You can simply plug in the winston instance as the logger object:
var winston = require('winston');
io.set('logger', winston);

Related

Verify hapi server.log is being called with expected message

I have a requirement to verify that certain actions are being logged to the server and would like to know why I'm having trouble stubbing the call to hapi server.log().
In my unit tests I instantiate a hapi server using:
const Hapi = require('hapi');
const server = new Hapi.Server();
I have my stub setup as:
const Sinon = require('sinon');
const logStub = Sinon.stub(server, 'log');
I am using server.inject to call the endpoint that I expect to call server.log. When I debug the test, I have a breakpoint set to verify that server.log is being called in my endpoint and I have a breakpoint in my unit test to verify that the logStub is being called. However, when I call this:
server.inject(localRequest).then(() => {
const spyCall = logStub.getCall(0);
})
spyCall is null and if I inspect logStub, called is false and the callCount is 0, despite server.log being called in my endpoint.
What am I missing here? Does calling server.inject cause an issue with stubbing methods on the hapi server?
The best solution I have been able to find is to use the server.once method on the hapi server.
I neglected to mention in my question that I'm using hapi version 16.6.2 so this solution may not work for the latest version of hapi as it is much different.
server.once({
name: 'log',
filter: 'myTag',
}, (update) => {
Code.expect(update.data).to.equal('expectedMessage');
});
Using this approach allowed me to specify the event 'log' and the specific tag (or tags) for my log event. Hope this helps someone else!

Is it possible to use winston logging and debug module together?

I use winston logging because I use its features like different logging levels, multiple transports, etc.
But I also like debug's namespace feature. Besides, express already uses it. So is it possible to use them together, e.g. to let winston logging have namespace?
After using several different loggers I gain more insight about nodejs loggers, now I believe they are not supposed to be used together b/c they are designed for different purposes. On the other hand, morgan and winston can be used together, e.g. Node.js - logging / Use morgan and winston, morgan and debug can be used together too, Nodejs - How to use morgan with debug
But first of all, to quote from Logging in Node.js done right
Setting up proper logging in Node.js applications can be bit
overwhelming at first due to the plethora of modules available through
NPM.
That was indeed my situation when I had morgan, winston, debug together. But then I realized they are for different purposes with overlaps. So I use debugjs when I really debug an issue instead of using console.log(some said debugjs is not a logger). After I am done with it I turn that debug off.
Morgan is to log express HTTP request specifically. Better to use it in dev/prod env for different purposes.
Using different log levels for Winston in dev/prod env is probably a common practice. I can also use express-winston to log HTTP request instead of using morgan.
Winston uses a different log level to turn off some log, unlike debugjs to use namespace to turn log off so I don't think they can work together.
--- update 2021 ---
Since I first answered my own question in 2018, I was asked several times about the log level related question. I found an issue opened against debugjs confirmed what I said about debug, to quote the answer from its current maintainer
Debug isn't a general purpose logging library, it's meant to
conditionally turn on debug logs. There is no concept of log levels.
Instead, break up your namespaces into different components and enable
the ones you care about
It can be useful to start passing debug(...) calls into winston. You can override the debug.log function to achieve that.
const logger = require('./v1/lib/logger'); //my winston logger
const util = require('util');
const debug = require('debug');
//for testing and dev use the regular debug (optional)
if (process.env.NODE_ENV === 'production') {
debug.log = (...args) => logger.info(util.format(...args))
}
module.exports = debug;
When dealing with debug and winston, you may also want to override formatArgs function, since debug.log is receiving already colored arguments (depending on enviroment) and it may have unexpected results in some cases (e.g. setting env vs module loading order).
import debug from "debug";
import util from "util";
import winston from "winston";
// create winston logger
const logger = new winston.Logger({ /*...*/ });
// keep original arguments
debug.formatArgs = (args) => { /* do nothing */ };
// override logging (keep function to use `this`)
debug.log = function(...args) {
// log to winston
logger.log("info", {
// `this` is bound to debug instance
namespace: this.namespace,
// format as in `console.log`
message: util.format(...args),
// add message time
timestamp: new Date().toISOString(),
// optionally log also diff time
diff: '+' + debug.humanize(this.diff),
});
};
// enable all debug
debug.enable('*');

Transport Settings in Socket.IO 1.4.x

I have been tinkering with deployd on Heroku using this gist as a starting point:
https://gist.github.com/facultymatt/5373247
Line 20 of that server.js tries to set transports for socket.io like so:
server.sockets.manager.settings.transports = ["xhr-polling"];
But encounters this error:
Cannot read property 'settings' of undefined.
From research so far it seems this approach is deprecated in socket.io 1.4.5. However, if that's so I am not clear on how I should address this setting.
My question is similar to this one. But differs in that I seek to change the settings once socket.io is already constructed by and attached to an instance of deployd.
Set it on creation:
var server = deployd({
socketIo: {
options: { transports : ['xhr-polling'] }
}
});
Or if you can't do that, change it runtime (this is a hack):
server.sockets.server.eio.transports = ['xhr-polling'];
(This is still supported for backwards compatibility:)
server.sockets.server.set('transports', ['xhr-polling']);

No entries in log file when using logging library

I do not know exactly if this is a issue resolving around forever or the libraries I tried but maybe someone can help here.
I was using console.log() through my application (express) to write logs. Now I've switched to a more feature packed logging library, namely Winston.js. Configured winston like this:
var winston = require('winston');
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {timestamp: true});
and replaced my console.log() entries with winston.info/winston.error, you name it. After I launched my app with node app.js everything went as expected. So I tried to run it with forever, since in production I run it that way.
Now I encountered the problem that the whole log file from forever, using just forever start app.js, was empty. Not a single log entry was there.
I replaced winston with log4js, but the log file remained empty when launching it with forever.
Is there anything I am missing right now and if so where is the problem?
Sincerly,
cschaeffler
It looks like you simply kept the Console transport without adding a transport for a file, e.g.,
winston.add(winston.transports.File, { filename: 'somefile.log' });

Logging configuration in sailsjs

I've started to use sailsjs not long ago and really love it ! (I'm a previous rails lover).
Anyway, I do not find the documentation on how to configure the logger transport (I'd like my log to be written in a file within the logs folder, and also to remove the console transport).
Usually, when using winston I use something like:
// Add transport file
winston.add(winston.transports.File, {
filename: some_filename
});
// Handle exceptions
winston.handleExceptions(new winston.transports.File({
filename: another_filename
}));
As sails already wraps Winston, I'm not sure how to do it in a clean way. Any idea or pointer towards an example ?

Resources