Socket
Socket
Sign inDemoInstall

pixl-logger

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pixl-logger - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

218

logger.js

@@ -6,3 +6,11 @@ // Generic Logger Class for Node.JS

var fs = require('fs');
var zlib = require('zlib');
var Path = require('path');
var os = require('os');
var async = require('async');
var mkdirp = require('mkdirp');
var glob = require('glob');
var Class = require("pixl-class");
var Tools = require("pixl-tools");

@@ -21,3 +29,3 @@ module.exports = Class.create({

if (!this.args.hostname) {
this.args.hostname = '';
this.args.hostname = os.hostname().toLowerCase();
}

@@ -45,6 +53,7 @@ },

delete args.now;
var dargs = get_date_args(now);
var dargs = Tools.getDateArgs(now);
// import args into object
for (var key in args) this.args[key] = args[key];
// for (var key in dargs) this.args[key] = dargs[key];

@@ -54,3 +63,3 @@ // set automatic column values

this.args.epoch = Math.floor( this.args.hires_epoch );
this.args.date = dargs.yyyy + '-' + dargs.mm + '-' + dargs.dd + ' ' + dargs.hh + ':' + dargs.mi + ':' + dargs.ss;
this.args.date = dargs.yyyy_mm_dd + ' ' + dargs.hh_mi_ss;

@@ -78,4 +87,10 @@ // support json 'data' arg

// file path may have placeholders, expand these if necessary
var path = this.path;
if (path.indexOf('[') > -1) {
path = Tools.substitute( path, this.args );
}
// append to log
fs.appendFile(this.path, line);
fs.appendFile(path, line);

@@ -117,38 +132,163 @@ // echo to console if desired

});
}
},
rotate: function() {
// rotate any log file atomically (defaults to our own file)
// 2 arg convention: dest_path, callback
// 3 arg convention: log_file, dest_path, callback
var log_file = '';
var dest_path = '';
var callback = null;
if (arguments.length == 3) {
log_file = arguments[0];
dest_path = arguments[1];
callback = arguments[2];
}
else if (arguments.length == 2) {
dest_path = arguments[0];
callback = arguments[1];
}
else throw new Error("Wrong number of arguments to rotate()");
if (!log_file) log_file = this.path;
if (log_file.indexOf('[') > -1) {
log_file = Tools.substitute( log_file, this.args );
}
// if dest path ends with a slash, add src filename + date/time stamp
if (dest_path.match(/\/$/)) {
var dargs = Tools.getDateArgs( Tools.timeNow() );
dest_path += Path.basename(log_file);
dest_path += '.' + (dargs.yyyy_mm_dd + '-' + dargs.hh_mi_ss).replace(/\W+/g, '-');
dest_path += '.' + Tools.generateUniqueID(16) + Path.extname(log_file);
}
// try fs.rename first
fs.rename(log_file, dest_path, function(err) {
if (err && (err.code == 'EXDEV')) {
// dest path crosses fs boundary, gotta rename + copy + rename + delete
// first, perform local rename in source log directory
var src_temp_file = log_file + '.' + Tools.generateUniqueID(32) + '.tmp';
fs.rename(log_file, src_temp_file, function(err) {
if (err) {
if (callback) callback(err);
return;
}
// copy src temp to dest temp file, then rename it
var dest_temp_file = dest_path + '.' + Tools.generateUniqueID(32) + '.tmp';
var inp = fs.createReadStream(src_temp_file);
var outp = fs.createWriteStream(dest_temp_file);
if (callback) inp.on('error', callback );
if (callback) outp.on('error', callback );
inp.on('end', function() {
// final rename
fs.rename(dest_temp_file, dest_path, function(err) {
if (err) {
if (callback) callback(err);
return;
}
// all done, delete src temp file
fs.unlink(src_temp_file, function(err) {
if (callback) callback(err);
});
});
} );
inp.pipe( outp );
} ); // src rename
} // EXDEV
else {
// rename worked, or other error
if (callback) callback(err);
}
} ); // fs.rename
},
archive: function(src_spec, dest_path, epoch, callback) {
// archive one or more log files, can use glob spec (defaults to our file).
// dest path may use placeholders: [yyyy], [mm], [dd], [hh], [filename], [hostname], etc.
// creates dest dirs as needed.
// if dest path ends in .gz, archives will be compressed.
var self = this;
if (!src_spec) src_spec = this.path;
if (!callback) callback = function() {};
// fill date/time placeholders
var dargs = Tools.getDateArgs( epoch );
for (var key in dargs) self.args[key] = dargs[key];
glob(src_spec, {}, function (err, files) {
// got files
if (files && files.length) {
async.eachSeries( files, function(src_file, callback) {
// foreach file
if (err) return callback(err);
// add filename to args
self.args.filename = Path.basename(src_file).replace(/\.\w+$/, '');
// construct final path
var dest_file = Tools.substitute( dest_path, self.args );
// rename local log first
var src_temp_file = src_file + '.' + Tools.generateUniqueID(32) + '.tmp';
fs.rename(src_file, src_temp_file, function(err) {
if (err) {
return callback( new Error("Failed to rename: " + src_file + " to: " + src_temp_file + ": " + err) );
}
// create dest dirs as necessary
mkdirp(Path.dirname(dest_file), function (err) {
if (err) {
return callback( new Error("Failed to make directories for: " + dest_file + ": " + err) );
}
if (dest_file.match(/\.gz$/i)) {
// gzip the log archive
var gzip = zlib.createGzip();
var inp = fs.createReadStream( src_temp_file );
var outp = fs.createWriteStream( dest_file, {flags: 'a'} );
inp.on('error', callback);
outp.on('error', callback);
inp.on('end', function() {
// all done, delete temp file
fs.unlink( src_temp_file, callback );
} );
inp.pipe(gzip).pipe(outp);
} // gzip
else {
// straight copy (no compress)
var inp = fs.createReadStream( src_temp_file );
var outp = fs.createWriteStream( dest_file, {flags: 'a'} );
inp.on('error', callback);
outp.on('error', callback);
inp.on('end', function() {
// all done, delete temp file
fs.unlink( src_temp_file, callback );
} );
inp.pipe( outp );
} // copy
} ); // mkdirp
} ); // fs.rename
}, callback ); // eachSeries
} // got files
else {
callback( err || new Error("No files found matching: " + src_spec) );
}
} ); // glob
} // archive()
});
function get_date_args(thingy) {
// return hash containing year, mon, mday, hour, min, sec
// given epoch seconds
var date = thingy.getFullYear ? thingy : (new Date( thingy * 1000 ));
var args = {
year: date.getFullYear(),
mon: date.getMonth() + 1,
mday: date.getDate(),
hour: date.getHours(),
min: date.getMinutes(),
sec: date.getSeconds(),
msec: date.getMilliseconds()
};
args.yyyy = args.year;
if (args.mon < 10) args.mm = "0" + args.mon; else args.mm = args.mon;
if (args.mday < 10) args.dd = "0" + args.mday; else args.dd = args.mday;
if (args.hour < 10) args.hh = "0" + args.hour; else args.hh = args.hour;
if (args.min < 10) args.mi = "0" + args.min; else args.mi = args.min;
if (args.sec < 10) args.ss = "0" + args.sec; else args.ss = args.sec;
if (args.hour >= 12) {
args.ampm = 'pm';
args.hour12 = args.hour - 12;
if (!args.hour12) args.hour12 = 12;
}
else {
args.ampm = 'am';
args.hour12 = args.hour;
if (!args.hour12) args.hour12 = 12;
}
return args;
};

52

package.json
{
"name": "pixl-logger",
"version": "1.0.1",
"description": "A simple logging class which generates [bracket][delimited] log columns.",
"author": "Joseph Huckaby <jhuckaby@gmail.com>",
"homepage": "https://github.com/jhuckaby/pixl-logger",
"license": "MIT",
"main": "logger.js",
"repository": {
"type": "git",
"url": "https://github.com/jhuckaby/pixl-logger"
},
"bugs": {
"url": "https://github.com/jhuckaby/pixl-logger/issues"
},
"keywords": [
"logging",
"clear"
],
"dependencies": {
"pixl-class": ">=1.0.0"
},
"devDepenendcies": {
}
}
"name": "pixl-logger",
"version": "1.0.2",
"description": "A simple logging class which generates [bracket][delimited] log columns.",
"author": "Joseph Huckaby <jhuckaby@gmail.com>",
"homepage": "https://github.com/jhuckaby/pixl-logger",
"license": "MIT",
"main": "logger.js",
"repository": {
"type": "git",
"url": "https://github.com/jhuckaby/pixl-logger"
},
"bugs": {
"url": "https://github.com/jhuckaby/pixl-logger/issues"
},
"keywords": [
"logging",
"clear"
],
"dependencies": {
"async": "^1.0.0",
"mkdirp": "^0.5.1 || ^1.0.0",
"glob": "^5.0.0",
"pixl-class": ">=1.0.0",
"pixl-tools": ">=1.0.0"
},
"devDependencies": {}
}

@@ -197,4 +197,42 @@ # Overview

## Rotating Logs
To rotate a log file, call the `rotate()` method, passing in a destination filesystem path and a callback. This will atomically move the file to the destination directory/filename, attempting a rename, and falling back to a "copy to temp file + rename" strategy. Example:
```javascript
logger.rotate( '/logs/pickup/myapp.log', function(err) {
if (err) throw err;
} );
```
If you omit a filename on the destination path and leave a trailing slash, the source log filename will be appended to it.
You can actually rotate any log file you want by specifying three arguments, with the custom source log file path as the first argument. Example:
```javascript
logger.rotate( '/path/to/logfile.log', '/logs/pickup/otherapp.log', function(err) {
if (err) throw err;
} );
```
## Archiving Logs
You can also "archive" logs using the `archive()` method. Archiving differs from rotation in that the log file is atomically copied to a custom location which may contain date/time directories (all auto-created as needed), and then the file is compressed using gzip. You can archive any number of logs at once by using [filesystem glob syntax](https://en.wikipedia.org/wiki/Glob_%28programming%29). Example:
```javascript
var src_spec = '/logs/myapp/*.log';
var dest_path = '/archives/myapp/[yyyy]/[mm]/[dd]/[filename]-[hh].log.gz';
var epoch = ((new Date()).getTime() / 1000) - 1800; // 30 minutes ago
logger.archive( src_spec, dest_path, epoch, function(err) {
if (err) throw err;
} );
```
This example would find all the log files found in the `/logs/myapp/` directory that end in `.log`, and archive them to destination directory `/archives/myapp/[yyyy]/[mm]/[dd]/`, with a destination filename pattern of `[filename]-[hh].log.gz`. All the bracket-delimited placeholders are expanded using the timestamp provided in the `epoch` variable. The special `[filename]` placeholder expands to the source log filename, sans extension. All directories are created as needed.
# License
The MIT License
Copyright (c) 2015 Joseph Huckaby

@@ -201,0 +239,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc