UNPKG

wdym

Version:

Convert Common Log Format (CLF) into more useful (and human-readable) JSON and/or CSV.

88 lines (77 loc) 2.52 kB
'use strict' const WDYM = require('./wdym') const IncorrectFormatError = require('../custom/IncorrectFormatError') const ValidationError = require('../custom/ValidationError') const messages = require('../custom/messages') const { parse } = require('date-fns') class WDYM_JSON extends WDYM { /** * Transforms input stream in Common Log Format into useful JSON. * @param {stream.Readable} chunk - the input stream of data * @param {String} encoding - character encoding of the chunk * @param {Function} callback - called when processing is complete for the supplied chunk */ _transform(chunk, encoding, callback) { const input = chunk.toString() try { const json = this.toJSON(input) this.push(JSON.stringify(json)) } catch (err) { messages.incorrectFormatError(err.message) process.exit() } callback() } /** * Parses the CLF logs and converts them to a single JavaScript Object. * @param {String} clf - the CLF Logs * @throws {IncorrectFormatError} - when one (or more) of the logs is not in CLF * @throws {ValidationError} - when one (or more) of the logs' components fail to validate * @returns {Object} */ toJSON(clf) { const lines = clf.split(/\n/) let json = { log: [] } lines.forEach((line) => { const matches = super.isCLF(line) if (matches) { if ( !super._validateIP(matches[1]) || !super._validateHTTPStatusCode(matches[6]) ) { throw new ValidationError( 'One or more of the logs failed to validate' ) } const serverLog = { remoteHost: matches[1], remoteLogName: matches[2], authUser: matches[3], date: Date.parse(matches[4]) || this._parseDate(matches[4]) ? this._parseDate(matches[4]) : 'unreadable', request: matches[5], status: Number(matches[6]), size: Number(matches[7]) || 0, } json.log.push(serverLog) } else { throw new IncorrectFormatError( 'The log is not in Common Log Format (CLF)' ) } }) return json } _parseDate(date) { if (Date.parse(date)) return new Date(date) const strftime = /([\w:/]+\s[+\-]\d{4})/ if (date.match(strftime)) { const parsed = parse(date, 'd/MMM/yyyy:kk:mm:ss XX', new Date()) if (!isNaN(parsed)) return parsed } return null } } module.exports = WDYM_JSON