Express Morgan. Logging to the internal object - node.js

guys. I'd like to use express middleware logging tool 'morgan' and want to change some default behaviour.
As it's said in the documentation (https://github.com/expressjs/morgan/blob/master/README.md) one of the paramateres it takes is "stream" which defines the output. By default it outputs to the node console but we can change it to log to the specified file.
// create a write stream (in append mode)
var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'})
// setup the logger
app.use(morgan('combined', {stream: accessLogStream}))
I wonder if there is an opportunity to forward all the logs to the specified object on the server? I mean do something like this:
var obj = []
var foo = function(param) {obj.push(param)}
app.use(morgan('combined'), {stream: foo})
thanks in advance!

Related

Node.js reads the file but does not write JSON in the HTML

I'm currently running Node.js by Browserify for my website.
It reads the JSON file and I get the message through MQTT.
But the problem is that it seems like writefile does not work.
(Running this as node test.js in the terminal works by the way).
What is wrong with my code?
Moreover, Is this the best way to store any user data?
Thank you so much in advance.
Here's some part of my code
var fs = require("fs");
var path = require("path");
let newFile = fs.readFileSync('/home/capstone/www/html/javascript/test.json');
function testT() { //THIS WORKS FINE
let student0 = JSON.parse(newFile);
var myJSON = JSON.stringify(student0);
client.publish("send2IR", myJSON);
response.end();
};
function write2JSON() { //PROBLEM OF THIS CODE
const content = 'Some content!'
fs.writeFileSync('/home/capstone/www/html/javascript/test.json', content)
};
document.getElementById("blink").addEventListener("click", publish);
document.getElementById("write").addEventListener("click", write2JSON);
You cann't write directly for security reasons. For other hand you can use a server as API to do the filye system tasks and in the client only trigger the events.
This post is very related with your problem:
Is it possible to write data to file using only JavaScript?

Can I pass variable to required file?

In express, I'm trying to move my minification to a requierd file:
app.js:
var app = express();
var minify = require("./minify.js");
In that file I try to set my template engine.
minify.js:
var app = express();
app.engine('html', mustacheExpress());
Later when I try to use to use the rendering engine in app.js, I get the error that no template-engine is set. It works if I run it all in the same file. I think the problem is that I declare the app-variable twice. How can I pass the app-variable into minify.js?
The problem is that you define new app variable, and you currently instantiate brand new express instance by calling express().
What you need to do is start using functions so that you can pass params (there are other methods too, but this is one that will work for you):
// app.js
var app = express();
var minify = require('./minify'); // don't include .js!
minify(app); // CALL the function that minify.js exports, passing params
// minify.js
module.exports = function(app) {
// because app comes as a parameter, it's the very same you've created in app.js
app.engine('html', mustacheExpress());
}
Again, there are many different methods and maybe proper approaches, depending on what you want to do, but this will do the job in your case. Read more about NodeJS and it's require system.
You can pass 'app' from app.js to your minify by using function in your module like Andrey said. You can do it like this too for example :
minify.js
module.exports = {
setAppEngine : function(app) {
app.engine( [...] );
}
}
And calling it like this in your app.js:
app.js
var app = express();
var minify = require("./minify.js").setAppEngine(app);
This solution is very useful because you can set and call others methods in minify.js. For example, you can do with the same code in minify.js:
app.js
var app = express();
var minify = require("./minify.js");
minify.setAppEngine(app);

Nodejs blocks and can't process next requests during ZIP file streaming

I'm trying to create a simple app which will create ZIP on the fly containg a few files and stream them to the client. Almost works. The problem what I encountered is that the nodejs blocks when streaming is in progress. All pendig requests will be processed after finishing current streaming. But what is interesting, these pending requests will be processed concurrently! So it can do this! I don't understand, why nodejs (expressjs?) can't start processing next request during streaming one file and what I did wrong... :|
I'm using node-archiver as a stream source.
Here's my part of code:
var express = require('express');
var archiver = require('archiver');
var router = express.Router();
router.get('/job/:id', function(req, res) {
var job = req.jobs[req.params.id];
var archive = archiver('zip');
archive.pipe(res);
for (var n in job.files) {
var f = job.files[n];
archive.file(job.path + f, {name: f});
}
res.setHeader("content-type", "application/zip");
res.setHeader("Content-Disposition", 'attachment; filename="reports.zip"')
archive.finalize();
});
module.exports = router;
Any advices? Thanks!
EDIT: I've noticed another problem, completely not related with archiver. I have following basic app:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req, res) {
var stream = fs.createReadStream('file.blob');
stream.pipe(res);
});
server.listen(31922);
Tell me, why it get stuck in this case? Result is absolutely the same as using archiver. OS what I use is SmartOS (based on Open Solaris), it's Unix. Maybe this is a problem? Any ideas?
For all those of you struggling with similar problem. I'm being dumb perhaps. The solution is simple. Basically testing method was wrong. My browser (and other tested have similar behaviour) blocks processing next request from the same host name when previous one is not finished. And in this case this is not finished request as downloading is still in progress. Thanks for your help!
It seems that Archiver depends on synchronous code, there is recent issue open on github addressing this:
https://github.com/ctalkington/node-archiver/issues/85
Given that it is synchronous, that's probably where your block is comming from.
Quote:
This module depends on file-utils which in the README says: "this is a
set of synchronous utility. As so, it should never be used on a
Node.js server. This is meant for users/command line utilities."

How can I set up logging for node-mongod-native?

I am trying to set up logging for the native mongo driver for node. I've got the following snippet set up as a demonstration for what I am trying to do. Unfortunately nothing is being emitted on the console. Any ideas?
var express = require('express') ;
var app = express();
var http = require('http');
var mongod = require('mongodb');
var server_conf = new mongod.Server('localhost', 27017, {auto_reconnect:true});
//dummy logger
var logger = {
error:function(message, object) {console.log('anything')},
log:function(message, object) {console.log('anything')},
debug:function(message, object) {console.log('anything')}}
var db_container = {db: new mongod.Db('test', server_conf,
{w:1,journal:true, native_parser:true, logger: logger})}
app.use(express.bodyParser());
app.use(app.router);
db_container.db.open(function(err, index_info){
if(err) throw err;
var testcol = db_container.db.collection('testcol');
app.get('/', function(request, res){
testcol.insert({hello:"moto"}, function(err,doc){
if(err){
throw err;
}
testcol.find({}).toArray(function(err,docs){
res.send(docs);
});
});
});
http.createServer(app).listen(3000, function () {
console.log('Express server listening on port ' + '3000');
});
});
Replicated below is: a copy of the answer to this question I posted on the node-mongodb-native google group
After looking at the most recent version of the code (commit 0fd78b3278da8deac980cb876fcb2bf72eaafb79) it looks like logging isn't really implemented yet.
First some ground rules: If you create a server config object (http://mongodb.github.io/node-mongodb-native/api-generated/server.html?highlight=server#Server) and set the logger object there that's ok. If you create a Db() object and set a logger in its options then it will override any logger you have set its server config. If you create a MongoClient() object this is equivalent to new Db('test', serverOptions, options) so you can set your logger object in either serverOptions or options. I'm not going to cover MongoClient.Connect and what happens there because I don't care to look over that portion of the code.
I could only find usage of the logger object happening in connection.js where it's revealed that you actually need a few additional properties to get logging working.
i.e line 69
if(this.logger != null && this.logger.doDebug){
this.logger.debug("opened connection", this.socketOptions);
}
or line 307
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
There are many more doDebug/doError property lookups in connection.js that require logging to work. There is a very minimal amount of logging happening from the looks of it but if you want to enable it you need to set the doError/doLog/doDebug properties on your logger as well. I actually haven't tested this out since I don't have the proper setup here but from looking over the code this seems to be the case.

Node.js Logging

Is there any library which will help me to handle logging in my Node.Js application? All I want to do is, I want to write all logs into a File and also I need an options like rolling out the file after certain size or date.
I have incorporated log4js im trying to keep all the configuration details in one file and use only the methods in other application files for ease of maintenance. But it doesnt work as expected. Here is what I'm trying to do
var log4js = require('log4js');
log4js.clearAppenders()
log4js.loadAppender('file');
log4js.addAppender(log4js.appenders.file('test.log'), 'test');
var logger = log4js.getLogger('test');
logger.setLevel('ERROR');
var traceLogger = function (message) {
logger.trace('message');
};
var errorLogger = function (message) {
logger.trace(message);
};
exports.trace = traceLogger;
exports.error = errorLogger;
I have included this file in other files and tried
log.error ("Hello Error Message");
But it is not working. Is there anything wrong in this ?
Winston is a pretty good logging library. You can write logs out to a file using it.
Code would look something like:
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ json: false, timestamp: true }),
new winston.transports.File({ filename: __dirname + '/debug.log', json: false })
],
exceptionHandlers: [
new (winston.transports.Console)({ json: false, timestamp: true }),
new winston.transports.File({ filename: __dirname + '/exceptions.log', json: false })
],
exitOnError: false
});
module.exports = logger;
You can then use this like:
var logger = require('./log');
logger.info('log to file');
Scribe.JS Lightweight Logger
I have looked through many loggers, and I wasn't able to find a lightweight solution - so I decided to make a simple solution that is posted on github.
Saves the file which are organized by user, date, and level
Gives you a pretty output (we all love that)
Easy-to-use HTML interface
I hope this helps you out.
Online Demo
http://bluejamesbond.github.io/Scribe.js/
Secure Web Access to Logs
Prints Pretty Text to Console Too!
Web Access
Github
https://github.com/bluejamesbond/Scribe.js
Log4js is one of the most popular logging library for nodejs application.
It supports many cool features:
Coloured console logging
Replacement of node's console.log functions (optional)
File appender, with log rolling based on file size
SMTP, GELF, hook.io, Loggly appender
Multiprocess appender (useful when you've got worker processes)
A logger for connect/express servers
Configurable log message layout/patterns
Different log levels for different log categories (make some parts
of your app log as DEBUG, others only ERRORS, etc.)
Example:
Installation: npm install log4js
Configuration (./config/log4js.json):
{"appenders": [
{
"type": "console",
"layout": {
"type": "pattern",
"pattern": "%m"
},
"category": "app"
},{
"category": "test-file-appender",
"type": "file",
"filename": "log_file.log",
"maxLogSize": 10240,
"backups": 3,
"layout": {
"type": "pattern",
"pattern": "%d{dd/MM hh:mm} %-5p %m"
}
}
],
"replaceConsole": true }
Usage:
var log4js = require( "log4js" );
log4js.configure( "./config/log4js.json" );
var logger = log4js.getLogger( "test-file-appender" );
// log4js.getLogger("app") will return logger that prints log to the console
logger.debug("Hello log4js");// store log in file
You can also use npmlog by issacs, recommended in
https://npmjs.org/doc/coding-style.html.
You can find this module here
https://github.com/isaacs/npmlog
The "logger.setLevel('ERROR');" is causing the problem. I do not understand why, but when I set it to anything other than "ALL", nothing gets printed in the file. I poked around a little bit and modified your code. It is working fine for me. I created two files.
logger.js
var log4js = require('log4js');
log4js.clearAppenders()
log4js.loadAppender('file');
log4js.addAppender(log4js.appenders.file('test.log'), 'test');
var logger = log4js.getLogger('test');
logger.setLevel('ERROR');
var getLogger = function() {
return logger;
};
exports.logger = getLogger();
logger.test.js
var logger = require('./logger.js')
var log = logger.logger;
log.error("ERROR message");
log.trace("TRACE message");
When I run "node logger.test.js", I see only "ERROR message" in test.log file. If I change the level to "TRACE" then both lines are printed on test.log.
Winston is strong choice for most of the developers. I have been using winston for long. Recently I used winston with with papertrail which takes the application logging to next level.
Here is a nice screenshot from their site.
How its useful
you can manage logs from different systems at one place. this can be very useful when you have two backend communicating and can see logs from both at on place.
Logs are live. you can see realtime logs of your production server.
Powerful search and filter
you can create alerts to send you email if it encounters specific text in log.
and you can find more http://help.papertrailapp.com/kb/how-it-works/event-viewer/
A simple configuration using winston,winston-express and winston-papertrail node modules.
import winston from 'winston';
import expressWinston from 'express-winston';
//
// Requiring `winston-papertrail` will expose
// `winston.transports.Papertrail`
//
require('winston-papertrail').Papertrail;
// create winston transport for Papertrail
var winstonPapertrail = new winston.transports.Papertrail({
host: 'logsX.papertrailapp.com',
port: XXXXX
});
app.use(expressWinston.logger({
transports: [winstonPapertrail],
meta: true, // optional: control whether you want to log the meta data about the request (default to true)
msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
colorize: true, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response
}));
A 'nodejslogger' module can be used for simple logging. It has three levels of logging (INFO, ERROR, DEBUG)
var logger = require('nodejslogger')
logger.init({"file":"output-file", "mode":"DIE"})
D : Debug, I : Info, E : Error
logger.debug("Debug logs")
logger.info("Info logs")
logger.error("Error logs")
The module can be accessed at : https://www.npmjs.com/package/nodejslogger
Observe that errorLogger is a wrapper around logger.trace. But the level of logger is ERROR so logger.trace will not log its message to logger's appenders.
The fix is to change logger.trace to logger.error in the body of errorLogger.
Each answer is 5 6 years old, so bit outdated or depreciated. Let's talk in 2020.
simple-node-logger is simple multi-level logger for console, file, and rolling file appenders. Features include:
levels: trace, debug, info, warn, error and fatal levels (plus all and off)
flexible appender/formatters with default to HH:mm:ss.SSS LEVEL message
add appenders to send output to console, file, rolling file, etc
change log levels on the fly
domain and category columns
overridable format methods in base appender
stats that track counts of all log statements including warn, error, etc
You can easily use it in any nodejs web application:
// create a stdout console logger
const log = require('simple-node-logger').createSimpleLogger();
or
// create a stdout and file logger
const log = require('simple-node-logger').createSimpleLogger('project.log');
or
// create a custom timestamp format for log statements
const SimpleNodeLogger = require('simple-node-logger'),
opts = {
logFilePath:'mylogfile.log',
timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
},
log = SimpleNodeLogger.createSimpleLogger( opts );
or
// create a file only file logger
const log = require('simple-node-logger').createSimpleFileLogger('project.log');
or
// create a rolling file logger based on date/time that fires process events
const opts = {
errorEventName:'error',
logDirectory:'/mylogfiles', // NOTE: folder must exist and be writable...
fileNamePattern:'roll-<DATE>.log',
dateFormat:'YYYY.MM.DD'
};
const log = require('simple-node-logger').createRollingFileLogger( opts );
Messages can be logged by
log.info('this is logged info message')
log.warn('this is logged warn message')//etc..
PLUS POINT: It can send logs to console or socket. You can also append to log levels.
This is the most effective and easy way to handle logs functionality.
Here is lightweight module for logging data with full stack trace
#grdon/logger
const logger = require('#grdon/logger')({
defaultLogDirectory : __dirname + "/logs",
})
// ...
logger(someParams, 'logfile.txt')
logger(anotherParams, 'anotherLogFile.log')

Resources