Permalink
Browse files

Add HTTP request logging

  • Loading branch information...
1 parent 6658f32 commit aff949dbabdce4e5b12150f4aa26a4270d2022ae @jcheng5 jcheng5 committed Jan 9, 2013
Showing with 65 additions and 7 deletions.
  1. +41 −2 lib/main.js
  2. +13 −3 lib/router/config-router.js
  3. +8 −1 lib/router/shiny-server-rules.config
  4. +2 −1 package.json
  5. +1 −0 test/config/good.config
View
@@ -17,7 +17,9 @@ var fs = require('fs');
var path = require('path');
var url = require('url');
var util = require('util');
+var connect = require('connect');
var optimist = require('optimist');
+var Q = require('q');
var qutil = require('./core/qutil');
var shutdown = require('./core/shutdown');
var proxy_http = require('./proxy/http');
@@ -47,7 +49,6 @@ logger.info(versionString);
var configFilePath = '/etc/shiny-server/shiny-server.conf';
if (optimist.argv._.length >= 1) {
configFilePath = path.resolve(optimist.argv._[0]);
- logger.info('Using config file "' + configFilePath + '"');
} else if (!fs.existsSync(configFilePath)) {
configFilePath = path.normalize(path.join(__dirname, '../config/default.config'));
}
@@ -92,12 +93,22 @@ server.on('clientError', function(err) {
});
sockjsServer.installHandlers(server);
+var requestLogger = null;
+server.on('request', function(req, res) {
+ if (requestLogger)
+ requestLogger(req, res);
+});
+
var loadConfig_p = qutil.serialized(function() {
return config_router.createRouter_p(configFilePath)
.then(function(configRouter) {
indirectRouter.setRouter(configRouter);
server.setAddresses(configRouter.getAddresses());
- logger.trace('Config loaded');
+ return createLogger_p(configRouter.accessLogSpec)
+ .then(function(logfunc) {
+ requestLogger = logfunc;
+ logger.trace('Config loaded');
+ });
})
.fail(function(err) {
if (err.code === 'ENOENT') {
@@ -110,6 +121,34 @@ var loadConfig_p = qutil.serialized(function() {
loadConfig_p().done();
+function createLogger_p(logSpec) {
+ if (!logSpec || !logSpec.path) {
+ logger.debug('No access log configured');
+ return Q.resolve(null);
+ }
+
+ logger.debug('Access log path: ' + logSpec.path);
+
+ try {
+ var stream = fs.createWriteStream(logSpec.path, {flags: 'a'});
+ var next = function(){};
+ var log = connect.logger({stream: stream, format: logSpec.format});
+ return Q.resolve(function(req, res) {
+ log(req, res, next);
+ });
+
+ } catch (err) {
+ return Q.reject(err);
+ }
+ return Q.nfcall(fs.open, logSpec.path, 'a', 0660)
+ .then(function(fd) {
+ })
+ .fail(function(err) {
+ logger.error('Error creating access log: ' + err.message);
+ return null;
+ });
+}
+
// On SIGHUP (i.e., initctl reload), reload configuration
process.on('SIGHUP', function() {
logger.info('SIGHUP received, reloading configuration');
@@ -30,12 +30,13 @@ function createRouter_p(configPath) {
configPath,
path.join(__dirname, 'shiny-server-rules.config'))
.then(function(conf) {
- return new ConfigRouter(createServers(conf));
+ return new ConfigRouter(conf);
});
}
-function ConfigRouter(servers) {
- this.servers = servers;
+function ConfigRouter(conf) {
+ this.servers = createServers(conf);
+ this.accessLogSpec = createAccessLogSpec(conf.getOne('access_log'));
}
(function() {
this.getAppSpec_p = function(req, res) {
@@ -114,6 +115,15 @@ function createServers(conf) {
return servers;
}
+function createAccessLogSpec(accessLogNode) {
+ if (!accessLogNode)
+ return null;
+ return {
+ path: accessLogNode.values.path,
+ format: accessLogNode.values.format
+ };
+}
+
/**
* Delegates requests to sub-routers (locations). Can indicate how well its
* configuration matches up to a request (`getScore`).
@@ -13,6 +13,13 @@ run_as {
maxcount 1;
}
+access_log {
+ desc "The file path of the HTTP access log.";
+ param String path "The file path where the access log should be written";
+ param String [format] "The log file format; see http://www.senchalabs.org/connect/logger.html" default;
+ at $;
+}
+
server {
desc "Declares an HTTP server. You need one of these for each port/IP address combination this Shiny Server instance should listen on.";
at $;
@@ -28,7 +35,7 @@ listen {
}
server_name {
- desc "Directs the enclosing server scope to only honor requests that have the given host headers (i.e. virtual hosts)."
+ desc "Directs the enclosing server scope to only honor requests that have the given host headers (i.e. virtual hosts).";
# Variadic parameter
param String names... "The virtual hostname(s) to bind this server to";
at server;
View
@@ -24,7 +24,8 @@
"stable" : "0.1.2",
"optimist" : "0.3.5",
"pause" : "0.0.1",
- "send" : "0.1.x"
+ "send" : "0.1.x",
+ "connect" : "2.7.x"
},
"license": "AGPL-3",
"engines": {
View
@@ -1,4 +1,5 @@
run_as shiny;
+#access_log /var/shiny-server/access_log tiny;
server {
listen 80;

0 comments on commit aff949d

Please sign in to comment.