in support-frontend/app/actions/CustomActionBuilders.scala [53:126]
private def chooseActionBuilder(
oktaAuthBuilder: ActionBuilder[OptionalAuthRequest, AnyContent],
): ActionBuilder[OptionalAuthRequest, AnyContent] =
PrivateAction andThen (
if (featureSwitches.authenticateWithOkta.contains(On))
oktaAuthBuilder
else
new AsyncAuthenticatedBuilder(asyncAuthenticationService.tryAuthenticateUser, cc.parsers.defaultBodyParser)
)
case class LoggingAndAlarmOnFailure[A](chainedAction: Action[A]) extends EssentialAction with SafeLogging {
private def pushMetric(cloudwatchEvent: AwsCloudWatchMetricPut.MetricRequest) = {
AwsCloudWatchMetricPut(AwsCloudWatchMetricPut.client)(cloudwatchEvent)
}
private def pushAlarmMetric = {
val cloudwatchEvent = AwsCloudWatchMetricSetup.serverSideCreateFailure(stage)
pushMetric(cloudwatchEvent)
}
private def pushHighThresholdAlarmMetric = {
val cloudwatchEvent = AwsCloudWatchMetricSetup.serverSideHighThresholdCreateFailure(stage)
pushMetric(cloudwatchEvent)
}
private def maybePushAlarmMetric(result: Result) = {
// We'll never alarm on these
val ignoreList = Set(
emailProviderRejectedCode,
invalidEmailAddressCode,
recaptchaFailedCode,
)
// We'll alarm on these, but only over a certain threshold
val highThresholdList = Set(
emailAddressAlreadyTakenCode,
)
if (result.header.status == 500) {
if (ignoreList.contains(result.header.reasonPhrase.getOrElse(""))) {
logger.info(
s"not pushing alarm metric for ${result.header.status} ${result.header.reasonPhrase} as it is in our ignore list",
)
} else if (highThresholdList.contains(result.header.reasonPhrase.getOrElse(""))) {
logger.info(
s"pushing higher threshold alarm metric for ${result.header.status} ${result.header.reasonPhrase}",
)
pushHighThresholdAlarmMetric
} else {
logger.error(
scrub"pushing alarm metric - non 2xx response. Http code: ${result.header.status}, reason: ${result.header.reasonPhrase}",
)
pushAlarmMetric
}
}
}
def apply(requestHeader: RequestHeader): Accumulator[ByteString, Result] = {
val accumulator = chainedAction.apply(requestHeader)
val loggedAccumulator = accumulator.through(Flow.fromFunction { (byteString: ByteString) =>
logger.info("incoming POST: " + byteString.utf8String)
byteString
})
loggedAccumulator
.map { result =>
maybePushAlarmMetric(result)
result
}
.recoverWith({ case throwable: Throwable =>
logger.error(scrub"pushing alarm metric - 5xx response caused by ${throwable}")
pushAlarmMetric
Future.failed(throwable)
})
}
}