Skip to content

Commit

Permalink
Merge pull request #2 from jobando89/logdev
Browse files Browse the repository at this point in the history
Abstraction of logging
  • Loading branch information
jobando89 committed Jan 23, 2018
2 parents 4b9a846 + 3c2cb04 commit eb902b1
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 118 deletions.
131 changes: 74 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,33 @@ The ***api*** folder should contain a ***controllers*** and a ***swagger*** fold

```javascript
tortilla.create(
{ // App definition
appRoot, //Start point of where to look for application folders
port, //The port to use to listen for requests. The default port is 8080

},
{ //Events and restify middleware
onServerStart, //Called before the server starts

afterStart, //Called after the server has started

onTerminate, //Called before the application is terminated

error, //Event handler when there is an unhandled exception in the application

middleware: [ //Referrer to Universal handlers for usage of middleware (http://restify.com/docs/home/)
//Array of functions
]
},
{ //Properties and error handling for controller methods
props: (req, res) => { //Add to the wrapper when used in the controller methods
{
definition: { // App definition
appRoot, //Start point of where to look for application folders
port, //The port to use to listen for requests. The default port is 8080
logger //Controller logger
},
errorHandler:(statusCode, message,reply)=>{ //Unhandled exceptions from the controller methods can be taken care of here.
//By default all errors will return http 500 with the error message of the exception
}
events: { //Events and restify middleware
onServerStart, //Called before the server starts

afterStart, //Called after the server has started

onTerminate, //Called before the application is terminated

error, //Event handler when there is an unhandled exception in the application

middleware: [ //Referrer to Universal handlers for usage of middleware (http://restify.com/docs/home/)
//Array of functions
]
},
wrapper: { //Properties and error handling for controller methods
props: (req, res) => { //Add to the wrapper when used in the controller methods
},
errorHandler:(statusCode, message,reply)=>{ //Unhandled exceptions from the controller methods can be taken care of here.
//By default all errors will return http 500 with the error message of the exception
}
},
serverLogger //Set logging method
}
);
```
Expand All @@ -82,41 +85,53 @@ tortilla.create(
const tortilla = require('tortilla-api');

tortilla.create(
{ // App definition
appRoot: __dirname,
port: 8080
},
{ //Events and restify middleware
onServerStart: function(context) {
console.log('Called before the server starts')
},
afterStart: function(context) {
console.log('Called after the server has started')
},
onTerminate: function(context) {
console.log('Called before the application is terminated')
},
error: function(err) {
console.log('unhandled exception in the application')
},
middleware: [
function(req, res, next) {
console.warn('run for all routes!');
return next();
}
]
},
{ //Properties and error handling for controller methods
props: function (req, res) {
const myQueryParam = req.getParam('myQueryParam');
return {
myQueryParam
};
{
definition: { // App definition
appRoot: __dirname,
port: 8080
},
errorHandler:(statusCode, message,reply)=>{
if (message.includes('doesn\'t exist')) {
return reply.notFound(message);
events: { //Events and restify middleware
onServerStart: function(context) {
console.log('Called before the server starts')
},
afterStart: function(context) {
console.log('Called after the server has started')
},
onTerminate: function(context) {
console.log('Called before the application is terminated')
},
error: function(err) {
console.log('unhandled exception in the application')
},
middleware: [
function(req, res, next) {
console.warn('run for all routes!');
return next();
}
]
},
wrapper: { //Properties and error handling for controller methods
props: function (req, res) {
const myQueryParam = req.getParam('myQueryParam');
return {
myQueryParam
};
},
errorHandler:(statusCode, message,reply)=>{
if (message.includes('doesn\'t exist')) {
return reply.notFound(message);
}
}
},
serverLogger: {
// Adding logging at the server level. Any logging logging library
// should work what implements the below are the
// possible logging levels
debug: console.log,
log: console.log,
info: console.log,
warn: console.log,
error: console.log
}
}
);
Expand All @@ -128,10 +143,11 @@ The controller uses the api method implementation of restify.
**For more information on restify properties see [http://restify.com/docs/server-api/](http://restify.com/docs/server-api/).**
```javascript
ControllerExample : Wrapper.wrap(async helper => {//Initialize controller method
//Helper has 3 native properties
//Helper native properties
helper.res // response property
helper.req// request property
helper.reply // setup replay for request needed to end http request
helper.logger // Log at different levels: debug, log, info, warn and error
return helper.res.reply.ok('Hello World');
})
```
Expand All @@ -144,6 +160,7 @@ const Wrapper = tortilla.wrapper;

module.exports={
ControllerExample : Wrapper.wrap(async helper => {
helper.logger.info('Hello World');
return helper.reply.ok('Hello World');
})
};
Expand Down
13 changes: 11 additions & 2 deletions config/default.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
port:
8080
loglevel:
'INFO'
log:
server:
level:
'INFO'
color:
'Yellow'
http:
level:
'DEBUG'
color:
'Yellow'
30 changes: 26 additions & 4 deletions example/start.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
const server = require('../');

global.tortillaApi = `${__dirname}/../`;
const config = require('config');
const {get} = require('lodash');
const guid = require('guid');
const Logger = require('logplease');
Logger.setLogLevel(get(config, 'log.server.level', 'INFO'));

const logger = (() => {
const color = get(config, 'log.server.color', 'Yellow');
const logger = Logger.create('Main Application', {color: Logger.Colors[color]});
return logger;
})();


server.create({
appRoot: `${__dirname}`
});
server.create(
{
definition: {
appRoot: `${__dirname}`,
logger:
(() => {
const color = get(config, 'log.http.color', 'Yellow');
const defaultLogger = Logger.create(`Request:${guid.raw()}`, {color: Logger.Colors[color]});
return defaultLogger;
})(),
},
serverLogger: logger
}
);
5 changes: 3 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"coveralls": "^3.0.0",
"eslint": "^4.12.0",
"istanbul": "^1.1.0-alpha.1",
"logplease": "^1.2.14",
"mocha": "^4.0.1",
"mocha-lcov-reporter": "^1.3.0",
"proxyquire": "^1.8.0",
Expand All @@ -43,7 +44,6 @@
"express": "^4.16.2",
"guid": "0.0.12",
"lodash": "^4.17.4",
"logplease": "^1.2.14",
"path": "^0.12.7",
"restify": "^6.3.4",
"stoppable": "^1.0.4",
Expand Down
29 changes: 19 additions & 10 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ const swaggerParser = require('swagger-parser');
const config = require('config');
const bodyParser = require('body-parser');
const busboyBodyParcer = require('busboy-body-parser');
const Logger = require('logplease');
const logger = Logger.create('Main Application', {color: Logger.Colors.Yellow});

Logger.setLogLevel(get(config, 'loglevel', 'INFO'));

const exitCode = {
success: 0,
Expand All @@ -25,8 +21,9 @@ const signals = [
'SIGHUP'
];

let logger;

const create = async (definition, events, wrapper) => {
const create = async ({definition, events, wrapper, serverLogger}) => {

const context = {
env: process.env, //Register run environment
Expand All @@ -35,14 +32,21 @@ const create = async (definition, events, wrapper) => {
definition: {
appRoot: __dirname, //This directory
port: get(config, 'port', 8080), //Default port
error: noop, //Return undefined
logger: get(definition, 'logger'), //Controller logger
...definition //Overwrite the properties
},
},
events,//{onServerStart,afterStart}
wrapper
wrapper,
};

logger = {
debug: (get(serverLogger, 'debug', noop)).bind(serverLogger),
log: get(serverLogger, 'log', noop).bind(serverLogger),
info: get(serverLogger, 'info', noop).bind(serverLogger),
warn: get(serverLogger, 'warn', noop).bind(serverLogger),
error: get(serverLogger, 'error', noop).bind(serverLogger)
};

if (isNil(get(context, 'internal.definition.appRoot'))) throw new Error('The application appRoot cannot be undefined');

Expand Down Expand Up @@ -92,14 +96,19 @@ const createServer = (context) => {
logger.error({route, err}, 'An unhandled exception has occurred');
res.send(500, 'An internal error has occurred.');
});

get(context, 'events.middleware', []).map(middleware => server.use(middleware)); //Register server middleware
server.use(mapWrapperProperties(context)); //Register middleware for wrapper use
server.use(bodyParser.json(context));
server.use(busboyBodyParcer());
server.use(setLogger(context));
get(context, 'events.middleware', []).map(middleware => server.use(middleware)); //Register server middleware
server.use(mapWrapperProperties(context)); //Register middleware for wrapper use
set(context, 'restify.server', server); ////Load server to current context
};

const setLogger = context => (req, res, next) => {
req.logger = get(context, 'internal.definition.logger', noop());
next();
};

const mapWrapperProperties = context => (req, res, next) => {
req.wrapperProperties = get(context, 'wrapper.props', noop);
res.errorHandler = get(context, 'wrapper.errorHandler');
Expand Down
25 changes: 16 additions & 9 deletions src/wrapper.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
const {get, keys, noop, isNil} = require('lodash');
const Promise = require('bluebird');
const guid = require('guid');
const config = require('config');
const Logger = require('logplease');
const logger = Logger.create(`Request:${guid.raw()}`, {color: Logger.Colors.Yellow});
Logger.setLogLevel(get(config, 'loglevel', 'INFO'));

class Wrapper {
constructor(req, res) {
constructor(req, res, logger) {
this._req = req;
this._res = res;
this._logger = logger;
}

static wrap(operation) {
return async (req, res) => {
const wrapper = new Wrapper(req, res);
const logger = get(req, 'logger');
const wrapper = new Wrapper(req, res, logger);
wrapper.logger.info('Start Request');
const wrapperFunction = get(req, 'wrapperProperties', noop);
const wrapperProperties = wrapperFunction(wrapper.req, wrapper.res);
keys(wrapperProperties).forEach(key => {
wrapper[key] = wrapperProperties[key];
});

try {
return await (!isNil(operation) ? operation :
await (!isNil(operation) ? operation :
() => {
wrapper.reply.ok();
return Promise.resolve;
}
)(wrapper);
return wrapper.logger.info('End Request');
}
catch (err) {
try {
Expand Down Expand Up @@ -73,7 +72,15 @@ class Wrapper {
}

get logger() {
return logger;
const defaultLogger =
{
debug: (get(this, '_logger.debug', noop)).bind(this._logger),
log: (get(this, '_logger.log', noop)).bind(this._logger),
info: (get(this, '_logger.info', noop)).bind(this._logger),
warn: (get(this, '_logger.warn', noop)).bind(this._logger),
error: (get(this, '_logger.error', noop)).bind(this._logger)
};
return defaultLogger;
}
}

Expand Down
Loading

0 comments on commit eb902b1

Please sign in to comment.