Skip to content

Commit

Permalink
Fixed bug in Scribe transcript rolling
Browse files Browse the repository at this point in the history
  • Loading branch information
CanyonCasa committed Sep 3, 2019
1 parent 9b41afa commit 7b260f6
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 59 deletions.
79 changes: 31 additions & 48 deletions bin/Cleanup.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
// Handles graceful application specific cleanup to avoid hung servers...

var cleanup = {
// define a default callback reference to be overridden by application...
callback: null,
// flag to prevent circular calls.
called: false,
// define a function to call for graceful exiting...
delay: 400,
gracefulExit: function (code) {
if (!this.called) {
this.called = true;
console.log("Graceful exit cleanup...");
if (this.callback) this.callback(); // do app specific cleaning once before exiting
code = (code!==undefined) ? code : 1; // assume non-zero (i.e. error) if not explicit
setTimeout(function() {process.exit(code);},this.delay); // no stopping!
};
}
};

// clean exit test...
process.on('beforeExit',
function () {
cleanup.gracefulExit(0);
}
);

// catch ctrl+c event and exit gracefully
process.on('SIGINT',
function () {
cleanup.gracefulExit(2);
}
);

//catch uncaught exceptions, trace, then exit gracefully...
process.on('uncaughtException',
function(e) {
console.log('Uncaught Exception...');
console.log(e.stack);
cleanup.gracefulExit(99);
}
);


module.exports = init = function init(cb=null) {
cleanup.callback = cb;
return cleanup;
};
// Handles graceful application specific cleanup to avoid hung servers...

var cleanup = {
callback: ()=>console.log("Graceful exit ..."), // default callback
called: false, // flag to prevent circular calls.
delay: 400,
gracefulExit: function (code=1) { // graceful exit call...
if (!this.called) {
this.called = true;
this.callback(); // do app specific cleaning once before exiting
setTimeout(process.exit,this.delay,code); // no stopping!
};
}
};

// catch clean exit ...
process.on('beforeExit', function () { cleanup.gracefulExit(0); });

// catch ctrl+c event and exit gracefully
process.on('SIGINT', function () { cleanup.gracefulExit(2); });

//catch uncaught exceptions, trace, then exit gracefully...
process.on('uncaughtException',
function(e) {
console.log('Uncaught Exception...');
console.log(e.stack);
cleanup.gracefulExit(99);
}
);

module.exports = init = (cb)=>{cleanup.callback=cb||null; return cleanup;};
21 changes: 11 additions & 10 deletions bin/Scribe.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ var level = {
warn: {txt: "WARN ", rank: 5, style: ['yellow','bold']},
error: {txt: "ERROR", rank: 6, style: ['red','bold']},
fatal: {txt: "FATAL", rank: 7, style: ['redBG','white','bold']},
flush: {txt: "FLUSH", rank: 8, style: ['cyan']}, // 'flush' always writes transcript
flush: {txt: "FLUSH", rank: 8, style: ['cyanBG','black']}, // 'flush' always writes transcript
};

// color styling function (applys only to console)...
var asStyle = (lvl, txt) => { level[lvl].style.forEach(function(s) { txt = colors[s](txt); }); return txt; };
var asStyle = (lvl='log', txt='') => { level[lvl].style.forEach(function(s) { txt = colors[s](txt); }); return txt; };

// constructor for Scribe class...
module.exports = Scribe = function Scribe(cfg={}) {
Expand All @@ -44,25 +44,26 @@ module.exports = Scribe = function Scribe(cfg={}) {
this.mask = cfg.mask || cfg.parent.mask || 'log';
// transcript object attributes include: file, level, bsize, and fsize; defaults below...
// buffering (i.e. bsize>0) will reduce file I/O, but may lose data on exit.
this.transcript = Object.assign({file: "../logs/"+this.tag+'.log', fsize: 500000, buffer:'', bsize: 10000, busy: false},cfg.transcript);
this.log("Scribe initialized for %s",this.tag.toUpperCase());
this.transcript = Object.assign({file: "../logs/"+this.tag+'.log', fsize: 200000, buffer:'', bsize: 10000, busy: false},cfg.transcript);
this.log("Scribe initialized for %s [%s]",this.tag.toUpperCase(),this.parent?'-/-':this.transcript.fsize+'/'+this.transcript.bsize);
};

// function to write output to rolling transcript file
Scribe.prototype.saveTranscript = function saveTranscript(ready) {
Scribe.prototype.saveTranscript = function saveTranscript(flag) {
if (this.transcript.busy) return; // already in process of saving transcript
if (ready) { // transcript file overflow checked
if (flag==='ready') { // transcript file overflow checked
let tmp = this.transcript.buffer;
this.transcript.buffer = '';
fs.writeFile(this.transcript.file,tmp,{encoding:'utf8',flag:'a'},(e)=>{if (e) console.log('ERROR: can not write to transcript...');});
} else {
this.transcript.busy = true;
fs.stat(this.transcript.file, (err, stats) => { // stats undefined if file not found...
if (stats && stats.size>this.transcript.fsize) { // roll transcript...
if ((flag===true) || (stats && stats.size>this.transcript.fsize)) { // roll transcript on flush or filesize...
let dx = new Date().toISOString().split(':').join('');
let parts = path.parse(this.transcript.file);
let bak = path.normalize(parts.dir + '/' + parts.name +'-' + dx + parts.ext);
fs.rename(this.transcript.file,bak,(e)=>{
this.debug("Rolling log: %s [%s]",bak,stats.size);
this.transcript.busy = false;
this.saveTranscript('ready');
});
Expand All @@ -82,7 +83,7 @@ Scribe.prototype.streamToTranscript = function streamToTranscript(line,flush) {
};
if (this.transcript.file) { // instance level transcripting if its log file defined...
this.transcript.buffer += line+((flush)?'\n':''); // extra linefeed if flushing to "paginate" log file.
if ((this.transcript.buffer.length>this.transcript.bsize) || flush) this.saveTranscript();
if ((this.transcript.buffer.length>this.transcript.bsize) || flush) this.saveTranscript(flush);
};
// otherwise scripting not saved to transcript file!
};
Expand Down Expand Up @@ -111,7 +112,7 @@ Scribe.prototype.error = function () { this.write('error',frmt.apply(this,argume
Scribe.prototype.fatal = function () { this.write('fatal',frmt.apply(this,arguments)); process.exit(100);};
Scribe.prototype.flush = function () { this.write('flush',frmt.apply(this,arguments)); }; // always write transcript

Scribe.prototype.styleAs = function (lvl=log,style='restore') {
Scribe.prototype.styleAs = function (lvl='log',style='restore') {
level[lvl].restore = (level[lvl].restore!==undefined) ? level[lvl].restore : level[lvl].style;
level[lvl].style = (style=='restore') ? level[lvl].restore : style;
};
Expand All @@ -122,4 +123,4 @@ Scribe.prototype.setMasterMask = function setMask(mask) {
s.savedMask = (s.savedMask!==undefined) ? s.savedMask : s.mask;
s.mask = (mask in level) ? mask : s.savedMask;
return s.mask;
};
};
2 changes: 1 addition & 1 deletion bin/homebrew.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var scribe = new Scribe(cfg.scribe);
scribe.info("Homebrew[%s] server setup in %s mode...", cfg.VERSION, process.env.NODE_ENV);

//ensure clean exit on Ctrl-C...; pass cleanup callback
require('./Cleanup')(()=>{scribe.flush('...Transcript Closed')}); // adds process event handlers
require('./Cleanup')(()=>{scribe.flush('Graceful exit ... closing transcript')}); // adds process event handlers

// dump the configuration for verbose debugging...
scribe.dump("CONFIG: %s", JSON.stringify(cfg,null,2));
Expand Down

0 comments on commit 7b260f6

Please sign in to comment.