Skip to content

Commit

Permalink
LIME-1343 - Implementing Overload Protection/Adding Vital signs logging
Browse files Browse the repository at this point in the history
Signed-off-by: ElliotMurphyGDS <[email protected]>
  • Loading branch information
ElliotMurphyGDS committed Dec 20, 2024
1 parent 7ba423e commit 36edc25
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 0 deletions.
72 changes: 72 additions & 0 deletions deploy/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,78 @@ Resources:
Period: "60"
Threshold: "20"

EventLoopDelayMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{($.eventLoopDelay = *)}"
MetricTransformations:
- MetricValue: $.eventLoopDelay
MetricName: EventLoopDelay
MetricNamespace: !Sub ${AWS::StackName}/LogMessages

EventLoopUtilizationIdleMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.eventLoopUtilization.idle = * }"
MetricTransformations:
- MetricValue: $.eventLoopUtilization.idle
MetricName: EventLoopUtilizationIdle
MetricNamespace: !Sub ${AWS::StackName}/LogMessages

EventLoopUtilizationActiveMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.eventLoopUtilization.active = * }"
MetricTransformations:
- MetricValue: $.eventLoopUtilization.active
MetricName: EventLoopUtilizationActive
MetricNamespace: !Sub ${AWS::StackName}/LogMessages

EventLoopUtilizationUtilizationMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.eventLoopUtilization.utilization = * }"
MetricTransformations:
- MetricValue: $.eventLoopUtilization.utilization
MetricName: EventLoopUtilizationUtilization
MetricNamespace: !Sub ${AWS::StackName}/LogMessages

RequestsPerSecondMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.requestsPerSecond.dynamic = * }"
MetricTransformations:
- MetricValue: $.requestsPerSecond.dynamic
MetricName: RequestsPerSecond
MetricNamespace: !Sub ${AWS::StackName}/LogMessages
Unit: Count/Second

AvgResponseTimeMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.avgResponseTime.dynamic = * }"
MetricTransformations:
- MetricValue: $.avgResponseTime.dynamic
MetricName: AvgResponseTime
MetricNamespace: !Sub ${AWS::StackName}/LogMessages
Unit: Count/Second

MaxConcurrentConnectionsMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref ECSAccessLogsGroup
FilterPattern: "{ $.maxConcurrentConnections = * }"
MetricTransformations:
- MetricValue: $.maxConcurrentConnections
MetricName: MaxConcurrentConnections
MetricNamespace: !Sub ${AWS::StackName}/LogMessages
Unit: Count
####################################################################
# #
# Alerts #
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"@govuk-one-login/frontend-analytics": "2.0.1",
"@govuk-one-login/frontend-language-toggle": "1.1.0",
"@govuk-one-login/frontend-passthrough-headers": "1.1.1",
"@govuk-one-login/frontend-vital-signs": "0.0.4",
"axios": "1.6.1",
"cfenv": "1.2.4",
"connect-dynamodb": "3.0.3",
Expand Down
22 changes: 22 additions & 0 deletions src/app-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const {
} = require("@govuk-one-login/di-ipv-cri-common-express/src/lib/i18next");
// Common express relies on 0/1 strings
const showLanguageToggle = APP.LANGUAGE_TOGGLE_DISABLED === "true" ? "0" : "1";
const {
frontendVitalSignsInitFromApp,
} = require("@govuk-one-login/frontend-vital-signs");

const init = (app, router) => {
setAPIConfig({
Expand Down Expand Up @@ -88,6 +91,25 @@ const create = (setup) => {
"views"
],
middlewareSetupFn: (app) => {
frontendVitalSignsInitFromApp(app, {
interval: 60000,
logLevel: "info",
metrics: [
"requestsPerSecond",
"avgResponseTime",
"maxConcurrentConnections",
"eventLoopDelay",
"eventLoopUtilization",
],
staticPaths: [
/^\/assets\/.*/,
"/ga4-assets",
"/javascript",
"/javascripts",
"/images",
"/stylesheets",
],
});
app.use(setHeaders);
},
dev: true
Expand Down
34 changes: 34 additions & 0 deletions src/app/passport/overloadProtection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const logger = require("hmpo-logger").get();
const router = require("express/lib/router");
const http = require('http')
const protect = require("overload-protection")("http", protectConfig);//is a reference to app here possible?

const protectConfig = {
production: process.env.NODE_ENV === 'production', // if production is false, detailed error messages are exposed to the client
clientRetrySecs: 1, // Retry-After header, in seconds (0 to disable) [default 1]
sampleInterval: 5, // sample rate, milliseconds [default 5]
maxEventLoopDelay: 400, // maximum detected delay between event loop ticks [default 42]
maxHeapUsedBytes: 0, // maximum heap used threshold (0 to disable) [default 0]
maxRssBytes: 0, // maximum rss size threshold (0 to disable) [default 0]
errorPropagationMode: false, // dictate behavior: take over the response
// or propagate an error to the framework [default false]
logging: "error", // set to string for log level or function to pass data to
logStatsOnReq: false // set to true to log stats on every requests
};

module.exports = function (req, res, next) {
//how do I set app.use in here, If we set to app in app-setup, this will work but not for all requests
//If I set
try {
http.createServer(function (req, res) {
if (protect(req, res) === true) {
router.use(protect);
logger.info("Overload protection enabled");
}
})

next();
} catch (error) {
return next(error);
}
};
4 changes: 4 additions & 0 deletions src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ const steps = require("./app/passport/steps");
const fields = require("./app/passport/fields");
const featureSets = require("./app/passport/featureSets");
const wizard = require("hmpo-form-wizard");
const overloadProtection = require("./app/passport/overloadProtection");

const init = (router) => {

router.use(overloadProtection);

router.use(getGTM);
router.use(getLanguageToggle);
router.use(setScenarioHeaders);
Expand Down

0 comments on commit 36edc25

Please sign in to comment.