diff --git a/keyserver/package.json b/keyserver/package.json --- a/keyserver/package.json +++ b/keyserver/package.json @@ -16,6 +16,7 @@ "clear-profile-logs": "rm -rf cpu_profiling_logs/", "dev-rsync": "yarn --silent chokidar --initial --silent -s 'src/**/*.json' 'src/**/*.cjs' -c 'yarn rsync > /dev/null 2>&1'", "dev": ". bash/source-nvm.sh && yarn concurrently --names=\"BABEL,RSYNC,NODEM\" -c \"bgBlue.bold,bgMagenta.bold,bgGreen.bold\" \"yarn babel-build --source-maps --watch\" \"yarn dev-rsync\" \". bash/source-nvm.sh && KEYSERVER=true NODE_ENV=development nodemon -e js,json,cjs --watch dist --no-warnings=ExperimentalWarning --loader=./loader.mjs dist/keyserver\"", + "dev-log-metrics": "KEYSERVER_ENDPOINT_METRICS_ENABLED=true yarn dev", "script": ". bash/source-nvm.sh && NODE_ENV=development node --loader=./loader.mjs", "test": "jest" }, diff --git a/keyserver/src/keyserver.js b/keyserver/src/keyserver.js --- a/keyserver/src/keyserver.js +++ b/keyserver/src/keyserver.js @@ -15,6 +15,7 @@ import { migrate } from './database/migrations.js'; import { jsonEndpoints } from './endpoints.js'; +import { logEndpointMetrics } from './middleware/endpoint_profiling.js'; import { emailSubscriptionResponder } from './responders/comm-landing-responders.js'; import { jsonHandler, @@ -62,6 +63,8 @@ : { maxAge: '1y', immutable: true }; const isCPUProfilingEnabled = process.env.KEYSERVER_CPU_PROFILING_ENABLED; + const areEndpointMetricsEnabled = + process.env.KEYSERVER_ENDPOINT_METRICS_ENABLED; if (cluster.isMaster) { const didMigrationsSucceed: boolean = await migrate(); @@ -123,6 +126,9 @@ server.use(cookieParser()); const setupAppRouter = router => { + if (areEndpointMetricsEnabled) { + router.use(logEndpointMetrics); + } router.use('/images', express.static('images')); router.use('/fonts', express.static('fonts')); router.use('/misc', express.static('misc')); diff --git a/keyserver/src/middleware/endpoint_profiling.js b/keyserver/src/middleware/endpoint_profiling.js new file mode 100644 --- /dev/null +++ b/keyserver/src/middleware/endpoint_profiling.js @@ -0,0 +1,27 @@ +// @flow + +import type { $Request, $Response, NextFunction } from 'express'; + +function logEndpointMetrics( + req: $Request, + res: $Response, + next: NextFunction, +): void { + const endpointName = req.url; + const requestTime = Date.now(); + + const onCompletion = () => { + const responseTime = Date.now(); + const endpointDuration = responseTime - requestTime; + const contentSize = res.get('Content-Length') ?? 'NaN'; + console.log( + `${endpointName}, ${endpointDuration.toFixed(2)}ms, ${contentSize} bytes`, + ); + }; + + res.on('finish', onCompletion); + + next(); +} + +export { logEndpointMetrics };