UNPKG

cdk-serverless-agentic-api

Version:

CDK construct for serverless web applications with CloudFront, S3, Cognito, API Gateway, and Lambda

322 lines 12.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.createApiGatewayAlarms = createApiGatewayAlarms; exports.createLambdaAlarms = createLambdaAlarms; exports.createCloudFrontAlarms = createCloudFrontAlarms; exports.createMonitoringResources = createMonitoringResources; const cloudwatch = __importStar(require("aws-cdk-lib/aws-cloudwatch")); const aws_cdk_lib_1 = require("aws-cdk-lib"); /** * Creates CloudWatch alarms for API Gateway metrics * * @param scope The construct scope * @param api The API Gateway REST API * @param dashboard The CloudWatch dashboard to add widgets to * @param constructId The ID of the parent construct */ function createApiGatewayAlarms(scope, api, dashboard, constructId) { // Create alarm for API Gateway 4xx errors new cloudwatch.Alarm(scope, 'ApiGateway4xxAlarm', { alarmName: `${constructId}-api-4xx-errors`, alarmDescription: 'API Gateway 4xx error rate is too high', metric: new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: '4XXError', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Sum', period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 10, evaluationPeriods: 2, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Create alarm for API Gateway 5xx errors new cloudwatch.Alarm(scope, 'ApiGateway5xxAlarm', { alarmName: `${constructId}-api-5xx-errors`, alarmDescription: 'API Gateway 5xx error rate is too high', metric: new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: '5XXError', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Sum', period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 5, evaluationPeriods: 2, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Create alarm for API Gateway latency new cloudwatch.Alarm(scope, 'ApiGatewayLatencyAlarm', { alarmName: `${constructId}-api-latency`, alarmDescription: 'API Gateway latency is too high', metric: new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: 'Latency', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Average', period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 5000, // 5 seconds evaluationPeriods: 3, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Add API Gateway metrics widget to dashboard dashboard.addWidgets(new cloudwatch.GraphWidget({ title: 'API Gateway Metrics', left: [ new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: 'Count', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Sum', }), ], right: [ new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: 'Latency', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Average', }), ], })); // Add error metrics widget dashboard.addWidgets(new cloudwatch.GraphWidget({ title: 'API Gateway Errors', left: [ new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: '4XXError', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Sum', }), new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName: '5XXError', dimensionsMap: { ApiName: api.restApiName, Stage: 'api', }, statistic: 'Sum', }), ], })); } /** * Creates CloudWatch alarms for Lambda function metrics * * @param scope The construct scope * @param lambdaFunctions Map of Lambda functions * @param dashboard The CloudWatch dashboard to add widgets to * @param constructId The ID of the parent construct */ function createLambdaAlarms(scope, lambdaFunctions, dashboard, constructId) { // Create alarms for each Lambda function that has health alarms enabled Object.entries(lambdaFunctions).forEach(([path, entry]) => { // Only create alarms if enableHealthAlarms is true if (!entry.config.enableHealthAlarms) { return; } // Generate a safe alarm ID from the path const safePath = path.replace(/[^a-zA-Z0-9]/g, ''); const alarmIdPrefix = `Lambda${safePath}`; // Create alarm for Lambda errors new cloudwatch.Alarm(scope, `${alarmIdPrefix}ErrorAlarm`, { alarmName: `${constructId}-lambda${path}-errors`, alarmDescription: `Lambda function for ${path} error rate is too high`, metric: entry.function.metricErrors({ period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 3, evaluationPeriods: 2, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Create alarm for Lambda duration new cloudwatch.Alarm(scope, `${alarmIdPrefix}DurationAlarm`, { alarmName: `${constructId}-lambda${path}-duration`, alarmDescription: `Lambda function for ${path} duration is too high`, metric: entry.function.metricDuration({ period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 25000, // 25 seconds (close to 30s timeout) evaluationPeriods: 3, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Add Lambda metrics to dashboard dashboard.addWidgets(new cloudwatch.GraphWidget({ title: `Lambda ${path} Metrics`, left: [ entry.function.metricInvocations(), entry.function.metricErrors(), ], right: [ entry.function.metricDuration(), ], })); }); } /** * Creates CloudWatch alarms for CloudFront metrics * * @param scope The construct scope * @param distribution The CloudFront distribution * @param dashboard The CloudWatch dashboard to add widgets to * @param constructId The ID of the parent construct */ function createCloudFrontAlarms(scope, distribution, dashboard, constructId) { // Create alarm for CloudFront 4xx errors new cloudwatch.Alarm(scope, 'CloudFront4xxAlarm', { alarmName: `${constructId}-cloudfront-4xx-errors`, alarmDescription: 'CloudFront 4xx error rate is too high', metric: new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: '4xxErrorRate', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Average', period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 5, // 5% error rate evaluationPeriods: 3, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Create alarm for CloudFront 5xx errors new cloudwatch.Alarm(scope, 'CloudFront5xxAlarm', { alarmName: `${constructId}-cloudfront-5xx-errors`, alarmDescription: 'CloudFront 5xx error rate is too high', metric: new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: '5xxErrorRate', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Average', period: aws_cdk_lib_1.Duration.minutes(5), }), threshold: 1, // 1% error rate evaluationPeriods: 2, treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, }); // Add CloudFront metrics to dashboard dashboard.addWidgets(new cloudwatch.GraphWidget({ title: 'CloudFront Metrics', left: [ new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: 'Requests', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Sum', }), ], right: [ new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: 'CacheHitRate', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Average', }), ], })); // Add error rate metrics dashboard.addWidgets(new cloudwatch.GraphWidget({ title: 'CloudFront Error Rates', left: [ new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: '4xxErrorRate', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Average', }), new cloudwatch.Metric({ namespace: 'AWS/CloudFront', metricName: '5xxErrorRate', dimensionsMap: { DistributionId: distribution.distributionId, }, statistic: 'Average', }), ], })); } /** * Creates monitoring resources including CloudWatch alarms and dashboards * * @param scope The construct scope * @param api The API Gateway REST API * @param lambdaFunctions Map of Lambda functions * @param distribution The CloudFront distribution * @param constructId The ID of the parent construct * @returns The created CloudWatch dashboard */ function createMonitoringResources(scope, api, lambdaFunctions, distribution, constructId) { // Create CloudWatch dashboard for monitoring const dashboard = new cloudwatch.Dashboard(scope, 'MonitoringDashboard', { dashboardName: `${constructId}-monitoring`, }); // Add API Gateway metrics to dashboard createApiGatewayAlarms(scope, api, dashboard, constructId); // Add Lambda function metrics to dashboard createLambdaAlarms(scope, lambdaFunctions, dashboard, constructId); // Add CloudFront metrics to dashboard createCloudFrontAlarms(scope, distribution, dashboard, constructId); return dashboard; } //# sourceMappingURL=monitoring.js.map