Mongoose Custom Logger
When Using Mongoose as MongoDb object modeling for NodeJs, one interesting feature is the possibility to log to standard output what Mongoose is actually doing while interfacing with MongoDB. This can be easily achieved by configuring Mongoose library itself:
mongoose.set('debug', true)
Which will print any action that Mongoose is performing (e.g. insert, update, remove, find) in a colored and very readable fashion.
This is basically an inner call of the library to console.log
.
However when employing a custom logger library, or a custom logging style, the Mongoose log style becomes soon non-compliant.
Imagine adding a logging library to your project or a logger that logs to file instead of stdout, or even a custom log format for logging to standard output.
In all the former cases Mongoose logs would be lost or not conformant.
Luckily Mongoose is providing an additional parameter to the previous method. From the official doc, the parameter can be either a writable stream or a callback for logging a message using a custom format.
mongoose.set('debug', function(collectionName, methodName, ...methodArgs) {}); // use custom function to log collection methods + arguments
If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arguments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')}).
As stated above the custom callback can be something like this:
function(collectionName, methodName, ...methodArgs) {
customLogger.log(`${collectionName}.${methodName}(${methodArgs.join(', ')})`)
}
where customLogger
is a custom logging library or imported dependency. The result is something like that:
While this is a step forward, this will just print a plain string, throwing away the nice colorization of the original Mongoose method, which is not cool!
Whereas for the Mongoose
string, it is just a matter of pure console coloring optimization, in the form of:
customLogger.log(`\x1B[0;36mMongoose:\x1B[0m:`);
The format of the nice part of the collection and operation performed is not straightforward to be printed.
But after digging a while in the lib, I found out that it uses a standard method of the native Node.js library util
, in particular util.inspect, which:
returns a string representation of object that is intended for debugging. The output of util.inspect may change at any time and should not be depended upon programmatically. Additional options may be passed that alter the result. util.inspect() will use the constructor's name and/or @@toStringTag to make an identifiable tag for an inspected value.
In the case of the Mongoose
lib, the object is slightly manipulated to remove new lines and extra white spaces.
The result is similar to:
util.inspect(m, false, 10, true).replace(/\n/g, '').replace(/\s{2,}/g, ' ');
So putting altogether, the final configuration of the Mongoose logging is something like that:
mongoose.set('debug', (collectionName, methodName, ...methodArgs) => {
const msgMapper = (m) => {
return util.inspect(m, false, 10, true)
.replace(/\n/g, '').replace(/\s{2,}/g, ' ');
};
customLogger.log(`\x1B[0;36mMongoose:\x1B[0m: ${collectionName}.${methodName}` + `(${methodArgs.map(msgMapper).join(', ')})`)
});
I am happy that I can finally achieve the same log output created by the Mongoose library with any custom logging library I may employ.
Top comments (1)
Really atemporal and useful article, Sergio. Many thanks!