View a markdown version of this page

Creating a CloudWatch dashboard with function name as a variable - AWS Identity and Access Management

Creating a CloudWatch dashboard with function name as a variable

The following code example shows how to:

  • Create a CloudWatch dashboard

  • Add Lambda metrics widgets with a function name variable

  • Verify the dashboard

  • Clean up resources

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # Script to create a CloudWatch dashboard with Lambda function name as a variable # This script creates a CloudWatch dashboard that allows you to switch between different Lambda functions # Set up logging with secure permissions LOG_FILE="${HOME}/.cloudwatch-dashboard-script.log" touch "$LOG_FILE" && chmod 600 "$LOG_FILE" exec > >(tee -a "$LOG_FILE") 2>&1 echo "$(date): Starting CloudWatch dashboard creation script" # Security: Set strict error handling set -euo pipefail trap 'handle_error "Script failed at line $LINENO"' ERR # Function to handle errors handle_error() { local error_msg="${1:-Unknown error}" echo "ERROR: $error_msg" >&2 echo "Resources created:" echo "- CloudWatch Dashboard: LambdaMetricsDashboard" echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "An error occurred. Proceeding with automatic cleanup..." echo "Cleaning up resources..." aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard 2>/dev/null || true # Clean up temporary files if [ -n "${TEMP_DIR:-}" ] && [ -d "$TEMP_DIR" ]; then rm -rf "$TEMP_DIR" fi rm -f dashboard-body.json echo "Cleanup complete." exit 1 } # Security: Validate AWS CLI is installed if ! command -v aws &> /dev/null; then handle_error "AWS CLI is not installed. Please install it and try again." fi # Check if AWS CLI is installed and configured echo "Checking AWS CLI configuration..." if ! aws sts get-caller-identity > /dev/null 2>&1; then handle_error "AWS CLI is not properly configured. Please configure it with 'aws configure' and try again." fi # Get the current region securely REGION=$(aws configure get region 2>/dev/null || echo "") if [ -z "$REGION" ]; then REGION="us-east-1" echo "No region found in AWS config, defaulting to $REGION" fi echo "Using region: $REGION" # Validate region format if ! [[ "$REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then handle_error "Invalid AWS region format: $REGION" fi # Check if there are any Lambda functions in the account echo "Checking for Lambda functions..." LAMBDA_FUNCTIONS=$(aws lambda list-functions --region "$REGION" --query "Functions[*].FunctionName" --output text 2>/dev/null || echo "") if [ -z "$LAMBDA_FUNCTIONS" ]; then echo "No Lambda functions found in your account. Creating a simple test function..." # Create a temporary directory for Lambda function code with secure permissions TEMP_DIR=$(mktemp -d) chmod 700 "$TEMP_DIR" trap 'rm -rf "$TEMP_DIR"' EXIT # Create a simple Lambda function cat > "$TEMP_DIR/index.js" << 'EOF' exports.handler = async (event) => { console.log('Event:', JSON.stringify(event, null, 2)); return { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; }; EOF # Zip the function code if ! cd "$TEMP_DIR"; then handle_error "Failed to change to temporary directory" fi if ! zip -q function.zip index.js; then handle_error "Failed to create zip file" fi # Create a role for the Lambda function with restricted trust policy ROLE_NAME="LambdaDashboardTestRole-$(date +%s)" TRUST_POLICY='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}' if ! ROLE_ARN=$(aws iam create-role \ --role-name "$ROLE_NAME" \ --assume-role-policy-document "$TRUST_POLICY" \ --query "Role.Arn" \ --output text 2>/dev/null); then handle_error "Failed to create IAM role for Lambda function" fi echo "Waiting for role to be available..." sleep 10 # Attach basic Lambda execution policy if ! aws iam attach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"; then aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true handle_error "Failed to attach policy to IAM role" fi # Create the Lambda function FUNCTION_NAME="DashboardTestFunction-$(date +%s)" if ! aws lambda create-function \ --function-name "$FUNCTION_NAME" \ --runtime nodejs18.x \ --role "$ROLE_ARN" \ --handler index.handler \ --zip-file fileb://function.zip \ --region "$REGION" > /dev/null 2>&1; then aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true handle_error "Failed to create Lambda function" fi # Invoke the function to generate some metrics echo "Invoking Lambda function to generate metrics..." for i in {1..5}; do aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null --region "$REGION" > /dev/null 2>&1 || true sleep 1 done # Go back to original directory cd - > /dev/null # Set the function name for the dashboard DEFAULT_FUNCTION="$FUNCTION_NAME" else # Use the first Lambda function as default DEFAULT_FUNCTION=$(echo "$LAMBDA_FUNCTIONS" | awk '{print $1}') echo "Found Lambda functions. Using $DEFAULT_FUNCTION as default." FUNCTION_NAME="" ROLE_NAME="" fi # Create a dashboard with Lambda metrics and a function name variable echo "Creating CloudWatch dashboard with Lambda function name variable..." # Create a JSON file for the dashboard body with secure permissions DASHBOARD_JSON="dashboard-body-$$.json" touch "$DASHBOARD_JSON" && chmod 600 "$DASHBOARD_JSON" # Escape special characters in region and function name for JSON REGION_ESCAPED=$(printf '%s\n' "$REGION" | sed 's:[\/&]:\\&:g') FUNCTION_ESCAPED=$(printf '%s\n' "$DEFAULT_FUNCTION" | sed 's:[\/&]:\\&:g') cat > "$DASHBOARD_JSON" << EOF { "widgets": [ { "type": "metric", "x": 0, "y": 0, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "Invocations", "FunctionName", "\${FunctionName}" ], [ ".", "Errors", ".", "." ], [ ".", "Throttles", ".", "." ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Lambda Function Metrics for \${FunctionName}", "period": 300 } }, { "type": "metric", "x": 0, "y": 6, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "Duration", "FunctionName", "\${FunctionName}", { "stat": "Average" } ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Duration for \${FunctionName}", "period": 300 } }, { "type": "metric", "x": 12, "y": 0, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "\${FunctionName}" ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Concurrent Executions for \${FunctionName}", "period": 300 } } ], "periodOverride": "auto", "variables": [ { "type": "property", "id": "FunctionName", "property": "FunctionName", "label": "Lambda Function", "inputType": "select", "values": [ { "value": "$FUNCTION_ESCAPED", "label": "$FUNCTION_ESCAPED" } ] } ] } EOF # Validate JSON before sending if ! jq empty "$DASHBOARD_JSON" 2>/dev/null; then handle_error "Invalid JSON generated for dashboard" fi # Create the dashboard using the JSON file if ! DASHBOARD_RESULT=$(aws cloudwatch put-dashboard \ --dashboard-name "LambdaMetricsDashboard-$(date +%s)" \ --dashboard-body file://"$DASHBOARD_JSON" \ --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to create CloudWatch dashboard." fi # Display any validation messages but continue if echo "$DASHBOARD_RESULT" | grep -q "DashboardValidationMessages"; then echo "Dashboard created with validation messages:" echo "$DASHBOARD_RESULT" echo "These validation messages are warnings and the dashboard should still function." else echo "Dashboard created successfully!" fi # Extract dashboard name from result DASHBOARD_NAME=$(echo "$DASHBOARD_RESULT" | grep -oP '"DashboardName"\s*:\s*"\K[^"]+' || echo "LambdaMetricsDashboard") # Verify the dashboard was created echo "Verifying dashboard creation..." if ! DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name "$DASHBOARD_NAME" --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to verify dashboard creation." fi echo "Dashboard verification successful!" echo "Dashboard details:" echo "$DASHBOARD_INFO" # List all dashboards to confirm echo "Listing all dashboards:" if ! DASHBOARDS=$(aws cloudwatch list-dashboards --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to list dashboards." fi echo "$DASHBOARDS" # Show instructions for accessing the dashboard echo "" echo "Dashboard created successfully! To access it:" echo "1. Open the CloudWatch console at https://console.aws.amazon.com/cloudwatch/" echo "2. In the navigation pane, choose Dashboards" echo "3. Select $DASHBOARD_NAME" echo "4. You should see a dropdown menu labeled 'Lambda Function' at the top of the dashboard" echo "5. Use this dropdown to select different Lambda functions and see their metrics" echo "" # Create a list of resources for cleanup RESOURCES=("- CloudWatch Dashboard: $DASHBOARD_NAME") if [ -n "${FUNCTION_NAME:-}" ]; then RESOURCES+=("- Lambda Function: $FUNCTION_NAME") RESOURCES+=("- IAM Role: $ROLE_NAME") fi # Prompt for cleanup with automatic yes echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "Resources created:" for resource in "${RESOURCES[@]}"; do echo "$resource" done echo "" echo "Proceeding with automatic cleanup..." CLEANUP_CHOICE="y" if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then echo "Cleaning up resources..." # Delete the dashboard if aws cloudwatch delete-dashboards --dashboard-names "$DASHBOARD_NAME" --region "$REGION" 2>/dev/null; then echo "Dashboard deleted successfully." else echo "WARNING: Failed to delete dashboard. You may need to delete it manually." fi # If we created a Lambda function, delete it and its role if [ -n "${FUNCTION_NAME:-}" ]; then echo "Deleting Lambda function..." if aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null; then echo "Lambda function deleted successfully." else echo "WARNING: Failed to delete Lambda function. You may need to delete it manually." fi echo "Detaching role policy..." if aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null; then echo "Role policy detached successfully." else echo "WARNING: Failed to detach role policy. You may need to detach it manually." fi echo "Deleting IAM role..." if aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null; then echo "IAM role deleted successfully." else echo "WARNING: Failed to delete IAM role. You may need to delete it manually." fi fi # Clean up the JSON file rm -f "$DASHBOARD_JSON" echo "Cleanup complete." fi echo "Script completed successfully!"

For a complete list of AWS SDK developer guides and code examples, see Using this service with an AWS SDK. This topic also includes information about getting started and details about previous SDK versions.