Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarlium committed Mar 30, 2016
0 parents commit ecda51c
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
; http://editorconfig.org
root = true

[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.idea
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Lambda Papertrail Logger
========================

A module for logging to Papertrail from AWS Lambda.

It will add metadata to the logs based on the context the function is run in, and format everything as JSON for easy reuse in other services.

This module is designed to be used within Aptoma, and is therefore rather opinionated with limited configuration options.

Installation
------------

npm install --save @aptoma/lambda-papertrail-logger

Usage
-----

```js
var createLogger = require('@aptoma/lambda-papertrail-logger');

exports.handler = function (event, context) {
var log = createLogger(context, papertrailConfig);
log.info('Executing handler', event);
};
```

The logger is an extension of `winston.Logger`.

In addition to being created with the relevant transports and formatters, it also exposes a `log.timerEvent(event)` method.

`log.timerEvent(event)` will format a timer event created by [@aptoma/timer](https://github.com/aptoma/node.timer) for sending to our internal event analytics service:

```js
var createLogger = require('@aptoma/lambda-papertrail-logger');
var timer = require('@aptoma/timer');

exports.handler = function (event, context) {
var elapsed = timer('ProcessingTime');
var log = createLogger(context, papertrailConfig);
log.timerEvent(elapsed());
};
```
112 changes: 112 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
'use strict';

require('./object.assign-polyfill');
var winston = require('winston');
var moment = require('moment-timezone');
var papertrailTransport = require('winston-papertrail').Papertrail;

/**
* @typedef {Object} LambdaLogger
* @augments {winston.Logger}
* @property {function} timerEvent
*/

/**
* @typedef {Object} TimerEvent
* @property {string} name
* @property {string} summary
* @property {float} msec
* @property {Array} hrtime
*/

/**
* @typedef {Object} LambdaContext
* @property {string} functionName
* @property {string} invokedFunctionArn
* @property {string} awsRequestId
* @property {string} functionVersion
*/

/**
* @typedef {Object} PapertrailConfig
* @property {string} host
* @property {int} port
* @see https://papertrailapp.com/account/destinations
*/

/**
* @param {LambdaContext} context
* @param {PapertrailConfig} papertrailConfig
* @returns {LambdaLogger}
*/
module.exports = function createLogger(context, papertrailConfig) {
var log = new (winston.Logger)({
transports: [
// This transport is used to output message to your local console, and is also the one picked up by Cloudwatch
new (winston.transports.Console)({
formatter: function (options) {
return timestamp() + ' ' + options.message;
}
})
]
});

// Only send logs to Papertrail if we're running on Lambda, and have provided config options
if (context.awsRequestId && papertrailConfig && papertrailConfig.host) {
addPapertrailLogger(context, papertrailConfig);
}

/**
* Log timer event, formatted for sending to Grimm
*
* @param {TimerEvent} event
*/
log.timerEvent = function (event) {
log.info(event.summary, {
name: event.name,
fields: {
msec: parseFloat(event.msec.toFixed(3))
},
tags: {
service: context.functionName
},
_tags: ['event']
});
};

return log;

/**
* @param {LambdaContext} context The context object supplied to the handler by AWS Lambda
* @param {PapertrailConfig} papertrailConfig
*/
function addPapertrailLogger(context, papertrailConfig) {
log.add(papertrailTransport, {
host: papertrailConfig.host,
port: papertrailConfig.port,
program: context.functionName,
hostname: getHostnameForARN(context.invokedFunctionArn),
includeMetaInMessage: false,
messageFormat: function (level, message, meta) {
return JSON.stringify(Object.assign({
_time: timestamp(),
msg: message
}, meta, {
version: context.functionVersion,
requestId: context.awsRequestId
}));
}
});
}

function getHostnameForARN(ARN) {
var arnParts = ARN.split(':');
return arnParts[3] ? 'aws-lambda-' + arnParts[3] : 'aws-lambda';
}

function timestamp() {
var m = moment();
m.tz('Europe/Oslo');
return m.format('YYYY-MM-DD HH:mm:ss.SSS');
}
};
25 changes: 25 additions & 0 deletions object.assign-polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
// Polyfill for Object.assign, while running Node.js < v4
// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
if (typeof Object.assign !== 'function') {
(function () {
Object.assign = function (target) {
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}

var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}
35 changes: 35 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@aptoma/lambda-papertrail-logger",
"version": "1.0.0",
"description": "A logger to send AWS Lambda logs to Papertrail",
"author": "Gunnar Lium <[email protected]>",
"main": "index.js",
"repository": {
"type": "git",
"url": "[email protected]:aptoma/lambda-papertrail-logger.git"
},
"scripts": {
"test": "jscs index.js",
"release": "release-it -n -i patch",
"release:minor": "release-it -n -i minor",
"release:major": "release-it -n -i major"
},
"dependencies": {
"moment-timezone": "^0.5.3",
"winston": "^2.2.0",
"winston-papertrail": "gunnarlium/winston-papertrail#temp-fixes"
},
"license": "MIT",
"jscsConfig": {
"preset": "yandex",
"disallowMultipleVarDecl": "exceptUndefined",
"maximumLineLength": null,
"validateIndentation": "\t"
},
"npm": {
"publish": true
},
"github": {
"release": true
}
}

0 comments on commit ecda51c

Please sign in to comment.