mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Add option to log every request start and end to loggly (#15243)
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
"LOGGLY_CLIENT_TOKEN": "token",
|
"LOGGLY_CLIENT_TOKEN": "token",
|
||||||
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
||||||
"LOGGLY_TOKEN": "example-token",
|
"LOGGLY_TOKEN": "example-token",
|
||||||
|
"LOG_REQUESTS_EXCESSIVE_MODE": "false",
|
||||||
"MAINTENANCE_MODE": "false",
|
"MAINTENANCE_MODE": "false",
|
||||||
"NODE_DB_URI": "mongodb://localhost:27017/habitica-dev?replicaSet=rs",
|
"NODE_DB_URI": "mongodb://localhost:27017/habitica-dev?replicaSet=rs",
|
||||||
"TEST_DB_URI": "mongodb://localhost:27017/habitica-test?replicaSet=rs",
|
"TEST_DB_URI": "mongodb://localhost:27017/habitica-test?replicaSet=rs",
|
||||||
|
|||||||
37
test/api/unit/middlewares/requestLogHandler.test.js
Normal file
37
test/api/unit/middlewares/requestLogHandler.test.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* eslint-disable global-require */
|
||||||
|
import requireAgain from 'require-again';
|
||||||
|
import {
|
||||||
|
generateRes,
|
||||||
|
generateReq,
|
||||||
|
generateNext,
|
||||||
|
} from '../../../helpers/api-unit.helper';
|
||||||
|
|
||||||
|
describe('requestLogHandler middleware', () => {
|
||||||
|
let res; let req; let
|
||||||
|
next;
|
||||||
|
const pathToMiddleWare = '../../../../website/server/middlewares/requestLogHandler';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
res = generateRes();
|
||||||
|
req = generateReq();
|
||||||
|
next = generateNext();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('attaches start time and request ID object to req', () => {
|
||||||
|
const middleware = requireAgain(pathToMiddleWare);
|
||||||
|
|
||||||
|
middleware.logRequestData(req, res, next);
|
||||||
|
|
||||||
|
expect(req.requestStartTime).to.exist;
|
||||||
|
expect(req.requestStartTime).to.be.a('number');
|
||||||
|
expect(req.requestIdentifier).to.exist;
|
||||||
|
expect(req.requestIdentifier).to.be.a('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next', () => {
|
||||||
|
const middleware = requireAgain(pathToMiddleWare);
|
||||||
|
const spy = sinon.spy();
|
||||||
|
middleware.logRequestData(req, res, spy);
|
||||||
|
expect(spy.calledOnce).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -59,7 +59,17 @@ export function generateReq (options = {}) {
|
|||||||
header (header) {
|
header (header) {
|
||||||
return this.headers[header];
|
return this.headers[header];
|
||||||
},
|
},
|
||||||
|
listeners: {},
|
||||||
session: {},
|
session: {},
|
||||||
|
on (key, func) {
|
||||||
|
if (!this.listeners[key]) {
|
||||||
|
this.listeners[key] = [];
|
||||||
|
}
|
||||||
|
this.listeners[key].push(func);
|
||||||
|
},
|
||||||
|
end () {
|
||||||
|
this.listeners.close.forEach(func => func());
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const req = defaultsDeep(options, defaultReq);
|
const req = defaultsDeep(options, defaultReq);
|
||||||
|
|||||||
@@ -31,10 +31,14 @@ import responseHandler from './response';
|
|||||||
import {
|
import {
|
||||||
attachTranslateFunction,
|
attachTranslateFunction,
|
||||||
} from './language';
|
} from './language';
|
||||||
|
import {
|
||||||
|
logRequestData,
|
||||||
|
} from './requestLogHandler';
|
||||||
|
|
||||||
const IS_PROD = nconf.get('IS_PROD');
|
const IS_PROD = nconf.get('IS_PROD');
|
||||||
const DISABLE_LOGGING = nconf.get('DISABLE_REQUEST_LOGGING') === 'true';
|
const DISABLE_LOGGING = nconf.get('DISABLE_REQUEST_LOGGING') === 'true';
|
||||||
const ENABLE_HTTP_AUTH = nconf.get('SITE_HTTP_AUTH_ENABLED') === 'true';
|
const ENABLE_HTTP_AUTH = nconf.get('SITE_HTTP_AUTH_ENABLED') === 'true';
|
||||||
|
const LOG_REQUESTS_EXCESSIVE_MODE = nconf.get('LOG_REQUESTS_EXCESSIVE_MODE') === 'true';
|
||||||
// const PUBLIC_DIR = path.join(__dirname, '/../../client');
|
// const PUBLIC_DIR = path.join(__dirname, '/../../client');
|
||||||
|
|
||||||
const SESSION_SECRET = nconf.get('SESSION_SECRET');
|
const SESSION_SECRET = nconf.get('SESSION_SECRET');
|
||||||
@@ -43,6 +47,10 @@ const TEN_YEARS = 1000 * 60 * 60 * 24 * 365 * 10;
|
|||||||
export default function attachMiddlewares (app, server) {
|
export default function attachMiddlewares (app, server) {
|
||||||
setupExpress(app);
|
setupExpress(app);
|
||||||
|
|
||||||
|
if (LOG_REQUESTS_EXCESSIVE_MODE) {
|
||||||
|
app.use(logRequestData);
|
||||||
|
}
|
||||||
|
|
||||||
if (ENABLE_CLUSTER) {
|
if (ENABLE_CLUSTER) {
|
||||||
app.use(domainMiddleware(server, mongoose));
|
app.use(domainMiddleware(server, mongoose));
|
||||||
}
|
}
|
||||||
|
|||||||
30
website/server/middlewares/requestLogHandler.js
Normal file
30
website/server/middlewares/requestLogHandler.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import logger from '../libs/logger';
|
||||||
|
|
||||||
|
export const logRequestEnd = (req, res) => {
|
||||||
|
const now = Date.now();
|
||||||
|
const requestTime = now - req.requestStartTime;
|
||||||
|
logger.info('Request completed', {
|
||||||
|
requestId: req.requestIdentifier,
|
||||||
|
method: req.method,
|
||||||
|
url: req.originalUrl,
|
||||||
|
duration: requestTime,
|
||||||
|
endTime: now,
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const logRequestData = (req, res, next) => {
|
||||||
|
req.requestStartTime = Date.now();
|
||||||
|
req.requestIdentifier = uuid();
|
||||||
|
logger.info('Request started', {
|
||||||
|
requestId: req.requestIdentifier,
|
||||||
|
method: req.method,
|
||||||
|
url: req.originalUrl,
|
||||||
|
startTime: req.requestStartTime,
|
||||||
|
});
|
||||||
|
req.on('close', () => {
|
||||||
|
logRequestEnd(req, res);
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user