Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add success rate alarms for log processor lambdas #285

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion bin/stacks/analytics-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface AnalyticsStackProps extends cdk.NestedStackProps {
envVars: Record<string, string>;
analyticsStreamArn: string;
stage: string;
chatbotSNSArn?: string;
}

/**
Expand All @@ -59,7 +60,7 @@ export class AnalyticsStack extends cdk.NestedStack {

constructor(scope: Construct, id: string, props: AnalyticsStackProps) {
super(scope, id, props);
const { quoteLambda, analyticsStreamArn, stage } = props;
const { quoteLambda, analyticsStreamArn, stage, chatbotSNSArn } = props;

/* S3 Initialization */
const rfqRequestBucket = new aws_s3.Bucket(this, 'RfqRequestBucket');
Expand Down Expand Up @@ -470,6 +471,61 @@ export class AnalyticsStack extends cdk.NestedStack {
],
})
);
let chatBotTopic: cdk.aws_sns.ITopic;
if (chatbotSNSArn) {
chatBotTopic = cdk.aws_sns.Topic.fromTopicArn(this, 'ChatbotTopic', chatbotSNSArn);
}

/* log processor alarms */
[quoteProcessorLambda, fillEventProcessorLambda, postOrderProcessorLambda, botOrderEventsProcessorLambda].forEach(
(lambda) => {
const successRateSev2Name = `${lambda.node.id}-SEV2-SuccessRate`;
const successRateSev3Name = `${lambda.node.id}-SEV3-SuccessRate`;

const errors = lambda.metricErrors({
period: cdk.Duration.minutes(5),
statistic: cdk.aws_cloudwatch.Stats.SUM,
label: `${lambda.node.id} Errors`,
});

const invocations = lambda.metricInvocations({
period: cdk.Duration.minutes(5),
statistic: cdk.aws_cloudwatch.Stats.SUM,
label: `${lambda.node.id} Invocations`,
});

const successRate = new cdk.aws_cloudwatch.MathExpression({
expression: '100 - 100 * errors / MAX([errors, invocations])',
usingMetrics: {
errors,
invocations,
},
label: `${lambda.node.id} Success Rate`,
});

const successRateSev2 = new cdk.aws_cloudwatch.Alarm(this, successRateSev2Name, {
metric: successRate,
threshold: 60,
evaluationPeriods: 1,
comparisonOperator: cdk.aws_cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
actionsEnabled: true,
});

const successRateSev3 = new cdk.aws_cloudwatch.Alarm(this, successRateSev3Name, {
metric: successRate,
threshold: 90,
evaluationPeriods: 1,
comparisonOperator: cdk.aws_cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
actionsEnabled: true,
});

if (chatBotTopic) {
successRateSev2.addAlarmAction(new cdk.aws_cloudwatch_actions.SnsAction(chatBotTopic));
successRateSev3.addAlarmAction(new cdk.aws_cloudwatch_actions.SnsAction(chatBotTopic));
}
}
);

// CDK doesn't have this implemented yet, so have to use the CloudFormation resource (lower level of abstraction)
// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisfirehose-deliverystream.html
const uraRequestStream = new aws_firehose.CfnDeliveryStream(this, 'uraRequestStream', {
Expand Down
7 changes: 4 additions & 3 deletions bin/stacks/api-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import * as aws_lambda from 'aws-cdk-lib/aws-lambda';
import * as aws_lambda_nodejs from 'aws-cdk-lib/aws-lambda-nodejs';
import * as aws_logs from 'aws-cdk-lib/aws-logs';
import * as aws_waf from 'aws-cdk-lib/aws-wafv2';
import { KmsStack } from './kms-stack'
import { Construct } from 'constructs';
import * as path from 'path';
import { KmsStack } from './kms-stack';

import { Metric } from '../../lib/entities';
import { STAGE } from '../../lib/util/stage';
Expand Down Expand Up @@ -156,7 +156,7 @@ export class APIStack extends cdk.Stack {
});

// KMS initialization
const kmsStack = new KmsStack(this, `${SERVICE_NAME}HardQuoteCosignerKey-1`)
const kmsStack = new KmsStack(this, `${SERVICE_NAME}HardQuoteCosignerKey-1`);

/*
* Firehose Initialization
Expand Down Expand Up @@ -184,7 +184,7 @@ export class APIStack extends cdk.Stack {
actions: ['kms:GetPublicKey', 'kms:Sign'],
effect: aws_iam.Effect.ALLOW,
})
)
);

lambdaRole.addToPolicy(
new aws_iam.PolicyStatement({
Expand Down Expand Up @@ -461,6 +461,7 @@ export class APIStack extends cdk.Stack {
envVars: props.envVars,
analyticsStreamArn: firehoseStack.analyticsStreamArn,
stage,
chatbotSNSArn,
});

const cronStack = new CronStack(this, 'CronStack', {
Expand Down
Loading