Skip to content

Instantly share code, notes, and snippets.

@crrobinson14
Created February 9, 2019 00:21
Show Gist options
  • Save crrobinson14/213b1865672f015b27f5a30835a9376f to your computer and use it in GitHub Desktop.
Save crrobinson14/213b1865672f015b27f5a30835a9376f to your computer and use it in GitHub Desktop.
QOS Logging Middleware for ActionHero
const { Initializer, api } = require('actionhero');
const fs = require('fs');
const shortid = require('../lib/shortid');
const safeApiRequestId = params => (params.apiRequestId || shortid(20))
.replace(/[^0-9a-zA-Z_-]/g, '')
.substring(0, 64);
function instrumentAction(data) {
const { action, params, response, connection } = data;
// Create an api request ID if one wasn't on the record, and sanitize it
const apiRequestId = safeApiRequestId(params);
params.apiRequestId = apiRequestId;
// Copy some fields to the response object for normal API calls
response.action = action;
response.apiRequestId = apiRequestId;
response.serverTime = +new Date();
data.actionQos = {
action,
apiRequestId,
connectionId: (connection || {}).id,
connectionType: (connection || {}).type,
startTime: Date.now(),
endTime: 0,
execTime: 0,
status: 0,
headers: {},
params: {},
};
// postProcessors are skipped on errors, so we set this ahead of time in case something throws.
data.response.status = 'ERROR';
}
function reportQOS(data) {
const { actionQos } = data;
/* istanbul ignore next */
if (!actionQos) {
return;
}
actionQos.endTime = Date.now();
actionQos.execTime = actionQos.endTime - actionQos.startTime;
actionQos.status = ((data.connection || {}).rawConnection || {}).responseHttpCode || 200;
// TODO: Add this record as a reportable metric maybe in CloudWatch?
data.response.status = 'OK';
}
process.on('unhandledRejection', (reason, p) => console.log('Unhandled Rejection at:', p, 'reason:', reason));
process.on('uncaughtException', err => fs.writeSync(1, `Caught exception: ${err}\n`));
module.exports = class QOSLog extends Initializer {
constructor() {
super();
this.name = 'QOSLog';
this.loadPriority = 500;
this.startPriority = 500;
this.stopPriority = 500;
}
async initialize() {
api.qosLog = QOSLog;
}
async start() {
// Check incoming requests for authentication requirements
api.actions.addMiddleware({
name: 'Request Processing : QOS',
global: true,
priority: 500,
preProcessor: instrumentAction,
postProcessor: reportQOS
});
}
async stop() {
// TODO: Flush QOS metrics if necessary
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment