docs: function createHttpLogger(server, serviceType, options) {
  	if (typeof service === 'object') {
  		options = serviceType;
  		// default service type: express
  		serviceType = 'express';
  	}
  
  	if (supportedHttpServices.indexOf(serviceType) === -1) {
  		throw new Error('Wrong service type');
  	}
  
  	// variable to indicate if this app is hosted by Arrow Cloud
  	const ConsoleLogger = require('./console'),
  		logDir = arrowCloudHosted ? arrowCloudLogDir : (options && options.logs || './logs');
  	let skipRequestLog;
  
  	// if not hosted, create the directory.
  	if (!arrowCloudHosted && !fs.existsSync(logDir)) {
  		fs.mkdirSync(logDir);
  	}
  
  	// turn off if specified we don't want logging
  	if (!arrowCloudHosted && options && !options.logSingleRequest) {
  		skipRequestLog = true;
  	}
  
  	if (options && options.adiPathFilter === undefined) {
  		options.adiPathFilter = [];
  	}
  
  	const serverName = server.name || (options && options.name),
  		consoleLogger = new ConsoleLogger(options),
  		serverLogger = bunyan.createLogger({
  			name: serverName || 'server',
  			serializers: {
  				req: bunyan.stdSerializers.req,
  				res: bunyan.stdSerializers.res
  			},
  			streams: [ {
  				level: options && options.level || 'info',
  				type: 'raw',
  				stream: consoleLogger
  			} ]
  		}),
  		// only create the request logger if we have a log directory to log to
  		requestLogger = !skipRequestLog && fs.existsSync(logDir) && bunyan.createLogger({
  			name: serverName || 'requests',
  			serializers: {
  				req: bunyan.stdSerializers.req,
  				res: bunyan.stdSerializers.res,
  				route: routeSerializer
  			},
  			streams: [ {
  				type: 'rotating-file',
  				period: '1d',
  				count: 1,
  				level: 'trace',
  				path: path.join(logDir, options && options.requestsLogFilename || 'requests.log')
  			} ]
  		}),
  		adiLogger = options && options.adiLogging && fs.existsSync(logDir) && bunyan.createLogger({
  			name: serverName || 'adiLogs',
  			serializers: {
  				req: bunyan.stdSerializers.req,
  				res: bunyan.stdSerializers.res,
  				route: routeSerializer
  			},
  			streams: [ {
  				type: 'rotating-file',
  				period: '1d',
  				count: 1,
  				level: 'trace',
  				path: path.join(logDir, 'adi-analytics.log')
  			} ]
  		});
  
  	serverLogger.requestLogger = requestLogger;
  	server.log = serverLogger;
  
  	(server.pre || server.use).call(server, function (req, resp, next) {
  		req.requestId = req.requestId || (serviceType === 'restify' ? req.getId() : require('uuid-v4')());
  		if (serviceType === 'restify') {
  			// record timestamp if using restify framework
  			req.started = req.started || process.hrtime();
  		}
  
  		if (options && options.logSingleRequest && (req.url && req.url !== '/arrowPing.json')) {
  			// we prefix with date to make it easier to sort logs by timestamp
  			const name = 'request-' + req.requestId,
  				logname = path.join(logDir, name + '.log'),
  				logstream = fs.createWriteStream(logname),
  				log = bunyan.createLogger({
  					name: name,
  					serializers: {
  						req: bunyan.stdSerializers.req,
  						res: bunyan.stdSerializers.res,
  						route: routeSerializer
  					},
  					streams: [ {
  						level: 'trace',
  						stream: logstream
  					}, {
  						level: options && options.level || 'info',
  						type: 'raw',
  						stream: consoleLogger
  					} ]
  				});
  			// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
  			log.info({
  				req_id: req.requestId,
  				req: req,
  				res: resp,
  				route: req.route,
  				start: true,
  				ignore: true
  			}, 'start');
  			req.log = log;
  			req.logname = logname;
  			req.logstream = logstream;
  			req._logname = name;
  			req.cleanStream = cleanStream;
  		}
  
  		next();
  	});
  
  	/**
  	 * derive the port if its in the host string.
  	 * @param  {Object} req a express req object
  	 * @return {string}     string representation of port
  	 */
  	function getPort(req) {
  		if (req.connection && req.connection.localPort) {
  			return req.connection.localPort.toString();
  		}
  		const host = req.headers && req.headers.host;
  		let protocolSrc = 80;
  		if (host && ((host.match(/:/g) || []).length) === 1) {
  			const possiblePort = host.split(':')[1];
  			protocolSrc = isNaN(possiblePort) ? protocolSrc : possiblePort;
  		}
  		return protocolSrc;
  	}
  	/**
  	 * derive the status string from the status code
  	 * @param  {Object} res express res object
  	 * @return {string}     success or error string
  	 */
  	function getStatus (res) {
  		let status;
  		const statusCode = res.statusCode;
  		if (statusCode) {
  			status = Math.floor(statusCode / 100) * 100;
  		}
  		switch (status) {
  			case 100:
  			case 200:
  			case 300:
  				return 'success';
  			default:
  				return 'failure';
  		}
  	}
  	/**
  	 * get the request id from the logname
  	 * @param  {Object} req express request object
  	 * @return {string}     string representation of request id
  	 */
  	function getCorrelationId(req) {
  		return req.requestId || null;
  	}
  
  	/**
  	 * Determine whether a certain URL is whitelisted based off the prefix
  	 * @param  {string}  url URL to check
  	 * @return {boolean}     Is the URL in the whitelist
  	 */
  	function isWhitelisted(url) {
  		return options.adiPathFilter.some(function (route) {
  			return url.substr(0, route.length) === route;
  		});
  	}
  
  	/**
  	 * A function to log request into file
  	 * @param  {Object} req  Request
  	 * @param  {Object} res  Response
  	 */
  	function logRequest(req, res) {
  		var responseTime = Math.round(req.duration),
  			shouldLogRequest = requestLogger && req && req.url && req.url !== '/arrowPing.json',
  			shouldADILog = options && options.adiLogging && adiLogger && req && req.url && isWhitelisted(req.url),
  			time = new Date().getTime(),
  			uri = (req.route && req.route.path) || req.path || (req.url && req.url.split('?')[0]),
  			localPort = getPort(req);
  
  		if (shouldLogRequest && req.log && req.logname && (req.logmetadata === undefined || req.logmetadata)) {
  			requestLogger.info({
  				req_id: req.requestId,
  				req: req,
  				res: res,
  				route: req.route,
  				name: req._logname,
  				logname: req.logname,
  				response_time: responseTime
  			});
  
  			const result = {
  				url: req.url,
  				req_headers: req.headers,
  				status: res.status,
  				req_id: req.requestId,
  				name: req._logname,
  				logname: req.logname,
  				response_time: responseTime
  			};
  			fs.writeFile(req.logname + '.metadata', JSON.stringify(result));
  		} else if (shouldLogRequest) {
  			requestLogger.info({
  				req_id: req.requestId,
  				response_time: responseTime,
  				route: req.route,
  				req: req,
  				res: res
  			});
  		}
  
  		if (shouldADILog) {
  			adiLogger.info({
  				type: 'transaction',
  				time: time,
  				path: uri,
  				protocol: req.protocol,
  				protocolSrc: localPort,
  				duration: responseTime,
  				status: getStatus(res),
  				serviceContexts: [
  					{
  						service: '',
  						monitor: '',
  						client: null,
  						org: null,
  						app: options.name,
  						method: '',
  						status: '',
  						duration: ''
  					}
  				],
  				customMsgAtts: {},
  				correlationId: getCorrelationId(req),
  				legs: [
  					{
  						uri: uri,
  						status: res.statusCode,
  						statusText: '',
  						method: req.method,
  						vhost: null,
  						wafStatus: 0,
  						bytesSent: parseInt(res.get('Content-Length'), 10) || null,
  						bytesReceived: parseInt(req.get('Content-Length'), 10) || null,
  						remoteName: '',
  						remoteAddr: '',
  						localAddr: '',
  						remotePort: '',
  						localPort: '',
  						sslsubject: null,
  						leg: 0,
  						timestamp: time,
  						duration: responseTime,
  						serviceName: uri,
  						subject: null,
  						operation: req.method + ' - ' + uri,
  						type: req.protocol,
  						finalStatus: ''
  					}
  				]
  			});
  		}
  		if (req.cleanStream) {
  			req.cleanStream();
  			req.cleanStream = null;
  		}
  	}
  
  	if (serviceType === 'restify') {
  		// restify framework
  
  		// by default, listen for the server's 'after' event but also let the
  		// creator tell us to use a different event. this is nice when you have
  		// additional things you want to do before ending the logging (after the server might
  		// have sent the response) that you want to log or capture before ending
  		const afterEvent = options && options.afterEvent || 'after';
  		server.on(afterEvent, function (req, res) {
  			// see if we've already calculated the duration and if so, use it
  			var duration = req.duration;
  			if (!duration) {
  				// otherwise we need to calculate it
  				const time = process.hrtime(req.started);
  				duration = (time[0] / 1000) + (time[1] * 1.0e-6);
  				req.duration = duration;
  			}
  			logRequest(req, res);
  		});
  	} else {
  		// express framework
  		const responseTimeMiddleWare = require('response-time');
  		server.use(responseTimeMiddleWare(function (req, res, duration) {
  			req.duration = duration;
  			logRequest(req, res);
  		}));
  	}
  
  	return serverLogger;
  }