On Azure, bunyan stops logging after a few seconds - node.js

I have a NodeJS web app and I've added logging via bunyan. Works perfectly on my desktop. On Azure it works perfectly for 1-10 seconds and then nothing else is ever logged. The app continues to run and operates correctly otherwise. I can't figure out why this is happening. Logging to a plain local file, not a blob or Azure Storage.
Log type is rotating-file, set to rotate 1/day and keep 3 days. The web app has Always On and ARR Affinity set to On, and Application Logging (Filesystem) though I'm not sure that factors here. Instance Count is 1 and Autoscale is not enabled. Node version is 8.7.0. In Console:
> df -h .
D:\home\site\wwwroot\logs
Filesystem Size Used Avail Use% Mounted on
- 100G -892G 99G 113% /d/home/site
Frankly I don't know what that's trying to tell me. Somehow we've used 113% of something, which is impossible. We've used a negative amount, which is impossible. There is still 99G/100G available, so we really are only using 1%. So is it a 'disk full' problem? I don't know. I haven't seen such an error message anywhere.
Prior, the app was using console.log(). We added code to intercept console.X and write to a file first, then call the normal function. The same thing happened - it would work for a few seconds and then not log anything else. I had assumed it was because some component of Azure was also intercepting console calls in order to redirect them to XXX-stdout.txt, and both of us doing that somehow broke it. Now it seems the cause may have been something else.
Does anyone know why this is happening?
11/12 - Created from scratch an app to log a heartbeat once/second and it worked fine. Also worked once/minute. I'll have to add in pieces from the failing project until it breaks.
11/13 - I don't think there's anything special about the logger configuration.
'use strict'
const bunyan = require('bunyan');
const fs = require('fs');
const path = require('path');
const logname = 'tracker';
const folder = 'logs';
const filename = path.join(folder, logname + ".json");
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}
var log = bunyan.createLogger({
name: logname,
streams: [{
type: 'rotating-file',
path: filename,
level: process.env.LOG_LEVEL || "info",
period: '1d', // daily rotation
count: 3 // keep 3 back copies
}]
});
module.exports = { log };
Still working on reproducing it with something less than the entire project.
11/14 - I've satisfied myself that after the bunyan logging stops the app is still continuing to call it. The "calling log2" console.logs are visible in the Azure Log Stream, but beyond ~30 seconds nothing more gets added to the bunyan log. I never see the "ERROR" logged. This is still in the context of the project, I still can't reproduce it separately.
var log2 = bunyan.createLogger({
name: logname,
streams: [{
type: 'rotating-file',
path: filename,
level: process.env.LOG_LEVEL || "info",
period: '1d', // daily rotation
count: 3 // keep 3 back copies
}]
});
var log = {};
log.info = function() {
console.log("calling log2.info");
try {
log2.info(...arguments);
} catch(err) {
console.log("log.info ERROR " + err);
}
}
11/14 - Changed from 'rotating-file' to 'file', same behavior. Enabled xxx logging and it prints the "writing log rec" message but does not add to the file. Something happened to the file stream? Added code to catch close/finish/cork right where we catch 'error' from the stream, didn't catch any of those events.
11/15 - I can see from pids and log messages that Azure is restarting my app. I don't know why, nothing in logging-errors.txt, nothing dire on stderr. I also don't know why that second run isn't logging to the file, when the first one did. But if I can figure out why it's restarting and prevent that, then I won't care about the second problem. Azure is so opaque to me.

After much head-banging we've determined that what we're trying to do isn't compatible with an Azure web app. We'll need to stand up a VM. Closing this question.

Related

gulp-eslint not outputting to file - unable to properly configure writableStream

Issue - User cannot get output to print to file for gulp-lint process
Documentation Reference It is observed in the documentation that a writeableStream is a valid configuration, but regrettably it does not denote or provide clarification on how to do this....and I have tried the solution below, along with others to no avail...so am seeking any insight / support that can be provided
Observations - other users had published guidance suggesting a stream similar to this, but when attempting this 2 things are observed....
The IntelliJ IDE notes that the parameter "writable" should be updated to "writableStream"
The build output generates the file, but the file is empty, therefore I am obviously missing something with respect to configuring / establishing the stream properly
Sample Code Block
'use strict';
const {src, task} = require('gulp');
const eslint = require('gulp-eslint');
const fs =require('fs');
task('lint', () => {
return src(['**/*.js', '!**/node_modules/**', '!**/handlebars.runtime-v4.1.2.js', '!**/parsley.js', '!**/slick.js','!*SampleTests.js'])
// Runs eslint
.pipe(eslint())
// Sets the format of the console
.pipe(eslint.format('table',fs.createWriteStream('eslint-result.xml')))
// To have the process exit with an error code (1) on lint error, return the stream and pipe to failAfterError last
.pipe(eslint.failOnError()
.pipe(eslint.results(results => {
// Called once for all ESLint results.
console.log(`Total Results: ${results.length}`);
console.log(`Total Warnings: ${results.warningCount}`);
console.log(`Total Errors: ${results.errorCount}`);
}))
)
});
A new day brings new results I guess....after running a build with this configuration again it worked..much to my surprise.
Note, I am using maven as a build process, and am invoking this using the maven-frontend plugin....and it is important to note that the result file will NOT appear until AFTER the build process has finished

Proper error logging for node applications

I am developing an express project which will have multiple modules/services in it. The folder structure looks mostly like this:
-- app.js
-- payment_service
-- routes.js
-- index.js
-- models
-- model_1.js
-- model_2.js
APIs in index.js are the only exposed APIs and they work as a gateway for all requests coming for this module/service.
Most of the services can throw operational error under many circumstances, so manual intervention may needed to fix things. So I need to:
Log errors properly with proper context so that some person/script can do the needful.
Figure out the reason of failure.
There will be dedicated teams owning each service. So I should be able to differentiate between error logs for each service so that it can be aggregated and forwarded to concerned person.
I decided to go with ELK stash so that I can generate reports by script.
The main problem that I am facing is that I can't maintain correlation between logs. For example; If a request comes and it travels through five functions and each function logs something then I can't relate those logs.
One way is to create a child logger for each request and pass it to all the functions but that seems to be extra overhead passing logger instance to all the functions.
Another option is to use something like verror and do the logging only at entry point of the service/module so that the whole context can be contained in the log. This approach looks ok for logging errors, however it can't help with info and debug logs - they help me a lot in development and testing phase.
For the sake of differentiating between error logs, I am going to create
A dedicated logger for each service with log level error.
An application wide generic logger for info and debug purpose.
Is this the correct approach?
What will be the best way so that I can achieve all the requirements in simplest way?
I'd recommend you use a logger and you don't need anything too complex. For example:
npm install 12factor-log
Then create a file in your root folder near app.js (or in a /lib folder is where I'd place libraries)
logger.js
const Log = require('12factor-log');
module.exports = (params) => {
return new Log(params);
}
Then in your modules, import your logger and pass in the module name when you instantiate it so you can track where statements come from...
model_1.js
var log = require('./logger')({name: 'model_1'});
// ...
log.info("Something happened here");
// ...
try {
// ...
catch (error) {
const message = `Error doing x, y, z with value ${val}`;
log.error(message);
throw new Error(message);
}
Then handle error gracefully at your controller -> view layer for user-friendly experience.
Your logs would print something like this:
{"ts":"2018-04-27T16:37:24.914Z","msg":"Something happened here","name":"model_1","type":"info","level":3,"hostname":"localhost","pid":18}
As far as correlation of logs, if you see in the output above it includes the hostname of the machine it's running on, and also the name of the module and severity level. You can import this JSON into Logstash and load into Elasticsearch and it will store JSON for easy search and indexing.
See: https://www.elastic.co/guide/en/logstash/current/plugins-filters-json.html
Logging is complex and many people have worked on it. I would suggest not doing so yourself.
So, not following my own advice, I created my own logging package:
https://www.npmjs.com/package/woveon-logger
npm install woveon-logger
This prints file and line numbers of errors and messages, has logging levels and aspect-oriented logging, and can dump a stack trace in one call. It even has color coding options. If you get stuck and need some feature in logging, let me know.
let logger1 = new Logger('log1', {level : 'info', debug : true, showname : true};
let logger2 = new Logger('log2', {level : 'verbose', debug : true, showname : true};
...
log1.info('Here is a log message, that is on line 23.');
log1.verbose('Does not show');
log2.verbose('Shows because log2 is verbose logging');
log2.setAspect('IO', true);
log2.aspect('IO', 'Showing aspect IO logging, for logs for IO related operations');
[2018-06-10T10:43:20.692Z] [INFO--] [log1 ] [path/to/myfile:23] Here is a log message, that is on line 23.
[2018-06-10T10:43:20.792Z] [VERBOS] [log2 ] [path/to/myfile:25] Shows because log2 is verbose logging
[2018-06-10T10:43:20.892Z] [IO----] [log2 ] [path/to/myfile:27] Showing aspect IO logging, for logs for IO related operations
Also, some other features like:
log1.throwError('Logs this as both a line of logging, and throws the error with the same message');
log1.printStack('Prints this label next to the stack trace.');
Hope it helps!
You can use grackle_tracking library https://www.getgrackle.com/analytics_and_tracking
It logs errors & traffic to your db.

How to write logs in node js

Recently i got a work to write log messages to my node js project.I am not sure about what exactly a log message mean,generally for a function we write 2 cases like below
exports.inserttopic = function (req, res) {
var topics = new Topics(req.body);console.log(topics)
topics.save(function (err, result) {
if (err) {
console.log(err);
return err;
}
if (result) {
data = { status: true, error_code: 0, result: result, message: 'Inserted successfully' };
}
res.json(data);
});
};
From the above code,i put console.log(err) for error case .is this a log message?If not how does log message s different from it?I heared something that log messages should be ride into a file.How can i do it,i surfed in google but i didnt come to end in understanding.I really troubled about it.Can anyone suggest me some help and post some good articles.Thanks.
A "log message" is only some Text Information which is offered by a program.
The message can be written to different output channels.
E.g. you are using the Console channel which is bound on the running program. This means when the program ends the log message may get lost if you don't save it explicitly (e.g. with a text-editor in a file).
The better way is to log into a so called "log-file".
You can write your own function which writes to a file or you can use some logging-framework.
The benefit on a logging framework is, that it mostly offers you the ability to choose, which output channel you prefer (for example also Database!), how the logging message has to look like (e.g. Date and Time at the beginning of each line) and that it offers you different severities.
Severities can be for example of type:
Error
Info
Debug
The Logging Framework (or your configuration) then decides how to handle the different severities.
Write the severities in different Logfiles (debug.log, error.log)
Write only messages over the configured Severity Level (e.g. Level Info skips debug messages)
...

Directory/File based logging selektor

I am looking for a logging solution for my node.js app that would allow me to set the logging level via file/folder selectors.
For example I would like to be able to set the logging for all files in /app/schema to 'info'. And all the rest to 'error'.
Exemplary configuration:
{
"*":"error",
"/app/schema":"info" //<--Regex expression would be great too.
}
I constantly comment/uncomment/remove logging statements when I need to examine something. I would rather do that via a configuration change and leave the logging files intact. A global debugging level just creates too way to much noise and volume (which matters when storing logs).
Is there something like this? Apache log4j is similar, you can set logging level on package level.
If I get your question right, I'd suggest Bunyan, it lets you configure as many log streams and log levels as you like, i.e. from the docs:
var log = bunyan.createLogger({
name: 'myapp',
streams: [
{
level: 'info',
stream: process.stdout // log INFO and above to stdout
},
{
level: 'error',
path: '/var/tmp/myapp-error.log' // log ERROR and above to a file
}
]
});
You'll have to set up the logic for each path with each log-level.

Log4js takes hours to write logfile

I am using log4js in my code to log the results and errors. The program runs for about 2,5 hours before the final console output is made and afterwards needs several hours to complete writing the logfile. The log is writing for 6 hours now (since the algorithm itself finished) and the filesize is 100mb.
The log will be about 1,5 million lines (when done).
Is it normal for the log to be written as slow as this? Are there "standard" mistakes to make when using log4js that I could check?
In case you want to know: The program is running on an Intel i5 with 8gb RAM and an SSD drive, so the hardware shouldn't be the problem I guess.
I am not sure what other information I can give you, just ask ahead if you need to know something.
Dropbox sounds like a good candidate. Any anti virus software could also interfere.
Firstly I would confirm what your system is capable of by creating a mini log4js benchmark for the various configurations available on your PC, then compare that to your application performance.
var Benchmark = require('benchmark');
var log4js = require('log4js');
log4js.clearAppenders();
log4js.loadAppender('file');
log4js.addAppender(log4js.appenders.file('NUL'), 'nulnulnul');
var lognul = log4js.getLogger('nulnulnul');
log4js.addAppender(log4js.appenders.file('c:/your_dropbox/test.log'), 'normallog');
var lognorm = log4js.getLogger('normallog');
log4js.addAppender(log4js.appenders.file('c:/tmp/test.log'), 'nodropbox');
var lognodr = log4js.getLogger('nodropbox');
log4js.addAppender(log4js.appenders.file('c:/virus-exception/test.log'), 'nodropvir');
var lognodv = log4js.getLogger('nodropvir');
var suite = new Benchmark.Suite;
// add tests
suite.add('Log#Nul', function() {
lognul.info("Some lengthy nulnulnul info messages");
})
.add('Log#normal', function() {
lognorm.info("Some lengthy normallog info messages");
})
.add('Log#NoDropbox', function() {
lognodr.info("Some lengthy nodropbox info messages");
})
.add('Log#NoVirusOrDropbox', function() {
lognodv.info("Some lengthy nodropvir info messages");
})
// add listeners
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
// run async
.run({ 'async': false });
If Dropbox or Virus software doesn't turn out to be the problem there are two Windows Sysinternal tools that will help you see what is going on your system when your process is running.
Process Explorer - Overall task manager/performance viewer
Gives you an overall view of your system so you can see which processes are doing what. You can also drill down into specific processes as well (right click/properties)
Process Monitor - Event profiler for processes.
Process Monitor is like a log file of all the system calls any process makes.
You can filter down to specific processes or calls so in your case you would be able to monitor Dropbox and your Node.js process and see if their access to the file in question is interleaved while Dropbox does it's work.

Resources