There are more AWS SDK examples available in the AWS Doc SDK Examples
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 -uo 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" \ --tags Key=project,Value=doc-smith Key=tutorial,Value=cloudwatch-dynamicdash \ --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 \ --tags project=doc-smith,tutorial=cloudwatch-dynamicdash \ --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 DASHBOARD_NAME="LambdaMetricsDashboard-$(date +%s)" if ! DASHBOARD_RESULT=$(aws cloudwatch put-dashboard \ --dashboard-name "$DASHBOARD_NAME" \ --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 # 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 API details, see the following topics in AWS CLI Command Reference.
-
Create read-only and read-write users
Creating an Amazon ECS service for the EC2 launch type