Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding some old stuff

  • Loading branch information...
commit 1c3cd6335ba3c8bbe66f2757e6701ea66b29d1e2 0 parents
@chriso authored
Showing with 271 additions and 0 deletions.
  1. +1 −0  .gitignore
  2. +20 −0 LICENSE
  3. +32 −0 README.md
  4. +196 −0 index.js
  5. +22 −0 package.json
1  .gitignore
@@ -0,0 +1 @@
+node_modules
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2012 Chris O'Hara <cohara87@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 README.md
@@ -0,0 +1,32 @@
+**nginx_parser** parse nginx log files in node.js
+
+### Installation
+
+```bash
+$ npm install nginxparser
+```
+
+### Usage
+
+To read a log file
+
+```javascript
+var NginxParser = require('nginx_parser');
+
+var parser = new NginxParser('$remote_addr - $remote_user [$time_local] '
+ + '"$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"');
+
+parser.read(path, function (row) {
+ console.log(row);
+});
+```
+
+To read from stdin, pass `-` as the path.
+
+To tail a log file (equivalent to `tail -F`)
+
+```javascript
+parser.read(path, { tail: true }, function (row) {
+ //...
+});
+```
196 index.js
@@ -0,0 +1,196 @@
+var fs = require('fs')
+ , buffers = require('buffertools')
+ , spawn = require('child_process').spawn;
+
+/**
+ * Create a log parser.
+ *
+ * @param {String} format
+ * @api public
+ */
+
+var Parser = module.exports = function (format) {
+ this.parser = format;
+ this.directives = {};
+
+ var directive = /\$([^ ]+)(.)?/g
+ , match, regex, i = 1;
+
+ while ((match = directive.exec(format))) {
+ this.directives[match[1]] = i++;
+ if (match[2]) {
+ match[2] = this.escape(match[2]);
+ regex = '([^' + match[2] + ']+)' + match[2];
+ } else {
+ regex = '(.+)$';
+ }
+ this.parser = this.parser.replace(match[0], regex);
+ }
+
+ this.parser = new RegExp(this.parser);
+};
+
+/**
+ * Parse a log file.
+ *
+ * @param {String} path
+ * @param {Object} options (optional)
+ * @param {Function} callback
+ * @api public
+ */
+
+Parser.prototype.read = function (path, options, callback) {
+ if (!path || path === '-') {
+ return this.stdin(options, callback);
+ } else if (options.tail) {
+ return this.tail(path, options, callback);
+ }
+ return this.stream(fs.createReadStream(path), options, callback);
+};
+
+/**
+ * Parse a log file and watch it for changes.
+ *
+ * @param {String} path
+ * @param {Object} options (optional)
+ * @param {Function} callback
+ * @api public
+ */
+
+Parser.prototype.tail = function (path, options, callback) {
+ var stream = spawn('tail', [ '-F', '-c', '+0', path]).stdout;
+ return this.stream(stream, options, callback);
+};
+
+/**
+ * Parse a log stream from STDIN.
+ *
+ * @param {Object} options (optional)
+ * @param {Function} callback
+ * @api public
+ */
+
+Parser.prototype.stdin = function (options, callback) {
+ return this.stream(process.stdin, options, callback);
+};
+
+/**
+ * Parse a log stream.
+ *
+ * @param {ReadableStream} stream
+ * @param {Object} options (optional)
+ * @param {Function} callback
+ * @api public
+ */
+
+Parser.prototype.stream = function (stream, options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ var self = this, overflow = new Buffer(0);
+ stream.on('data', function (data) {
+ var buffer = overflow.concat(data), newline = 0;
+ for (var i = 0, len = buffer.length; i < len; i++) {
+ if (buffer[i] === 10) {
+ self.parseLine(buffer.slice(newline, i), options, callback, stream);
+ newline = i + 1;
+ }
+ }
+ overflow = buffer.slice(newline);
+ });
+ stream.on('end', function () {
+ if (overflow.length) {
+ self.parseLine(overflow, options, callback, stream);
+ }
+ });
+ process.nextTick(function () {
+ stream.resume();
+ });
+ return stream;
+};
+
+/**
+ * Parse a log line.
+ *
+ * @param {Buffer} line
+ * @param {Object} options
+ * @param {Object} scope (optional)
+ * @api private
+ */
+
+Parser.prototype.parseLine = function (line, options, callback) {
+ var match = line.toString().match(this.parser)
+
+ if (!match) return;
+
+ var row = {
+ msec: null
+ , time_iso8601: null
+ , remote_addr: null
+ , query_string: null
+ , http_x_forwarded_for: null
+ , http_user_agent: null
+ , http_referer: null
+ , time_local: null
+ , request: null
+ , status: null
+ , request_time: null
+ , request_length: null
+ , pipe: null
+ , connection: null
+ , bytes_sent: null
+ , body_bytes_sent: null
+
+ , date: null
+ , timestamp: null
+ , ip: null
+ , ip_str: null
+ };
+
+ for (var key in this.directives) {
+ row[key] = match[this.directives[key]];
+ if (row[key] === '-') {
+ row[key] = null;
+ }
+ }
+
+ //Parse the timestamp
+ if (row.time_iso8601) {
+ row.date = new Date(row.time_iso8601);
+ } else if (row.msec) {
+ row.date = new Date(Number(row.msec.replace('.', '')));
+ }
+ if (row.date) {
+ row.timestamp = row.date.getTime();
+ }
+
+ //Parse the user's IP
+ if (row.http_x_forwarded_for) {
+ row.ip_str = row.http_x_forwarded_for;
+ } else if (row.remote_addr) {
+ row.ip_str = row.remote_addr;
+ }
+ if (row.ip_str) {
+ var ip = row.ip_str.split('.', 4);
+ row.ip = Number(ip[0]) * (2 << 23)
+ + Number(ip[1]) * (2 << 15)
+ + Number(ip[2]) * (2 << 7)
+ + Number(ip[3]);
+ }
+
+ callback(row);
+};
+
+/**
+ * Escape regular expression tokens.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+Parser.prototype.escape = function (str) {
+ return str.replace(new RegExp('[.*+?|()\\[\\]{}]', 'g'), '\\$&');
+};
+
22 package.json
@@ -0,0 +1,22 @@
+{ "name" : "nginxparser",
+ "description" : "Parse Nginx log files",
+ "version" : "0.1.0",
+ "homepage" : "http://github.com/chriso/nginx_parser",
+ "author" : "Chris O'Hara <cohara87@gmail.com>",
+ "bugs": {
+ "mail": "cohara87@gmail.com",
+ "url": "http://github.com/chriso/nginx_parser/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/chriso/nginx_parser.git"
+ },
+ "engines": { "node": ">=0.4.0" },
+ "dependencies": {
+ "buffertools": "*"
+ },
+ "licenses": [{
+ "type": "MIT",
+ "url": "http://github.com/chriso/nginx_parser/raw/master/LICENSE"
+ }]
+}
Please sign in to comment.
Something went wrong with that request. Please try again.